Angular HttpClient — GET, POST, PUT, DELETE
HttpClient
Angular provides the HttpClient for sending HTTP requests and making API calls to remote servers. HttpClient is available from the package @angular/common/http. In Angular 21, HttpClient is automatically provided in the root injector - you no longer need to call provideHttpClient() for basic usage.
Modern web browsers has two standard APIs for sending Http requests i.e. XMLHttpRequest interface and the fetch(). The HttpClientModule is built on top of the XMLHttpRequest interface. HttpClientModule wraps all the complexities of XMLHttpRequest interface and provides extra features such as:-
HttpClient Configuration
In Angular 21, HttpClient is provided in the root injector by default. For advanced usage such as adding interceptors, you can still configure it explicitly in app.config.ts. The steps below show the modern standalone approach:-
Step 1
In Angular 21, add provideHttpClient() to app.config.ts for custom configuration (e.g. interceptors). For basic usage it is auto-provided.
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideHttpClient, withFetch } from '@angular/common/http';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideHttpClient(withFetch()) // uses the Fetch API backend
]
};
Step 2
Inject HttpClient using the inject() function in a standalone component or service.
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class DataService {
private http = inject(HttpClient);
getUsers(): Observable<any[]> {
return this.http.get<any[]>('https://jsonplaceholder.typicode.com/users');
}
}
Step 3
Use the service in a standalone component with toSignal() to convert the Observable to a Signal.
import { Component, inject } from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import { DataService } from './data.service';
@Component({
selector: 'app-users',
standalone: true,
template: `
@for (user of users(); track user.id) {
<p>{{ user.name }} - {{ user.email }}</p>
}
`
})
export class UsersComponent {
private dataService = inject(DataService);
users = toSignal(this.dataService.getUsers(), { initialValue: [] });
}
HTTP Methods - GET, POST, PUT, DELETE
All HTTP methods return an Observable. You must subscribe or use toSignal() to get the data.
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
const BASE = 'https://jsonplaceholder.typicode.com';
@Injectable({ providedIn: 'root' })
export class ApiService {
private http = inject(HttpClient);
// GET
getPost(id: number) {
return this.http.get(`${BASE}/posts/${id}`);
}
// POST
createPost(data: object) {
return this.http.post(`${BASE}/posts`, data);
}
// PUT
updatePost(id: number, data: object) {
return this.http.put(`${BASE}/posts/${id}`, data);
}
// PATCH
patchPost(id: number, data: object) {
return this.http.patch(`${BASE}/posts/${id}`, data);
}
// DELETE
deletePost(id: number) {
return this.http.delete(`${BASE}/posts/${id}`, { responseType: 'text' });
}
}
Functional HTTP Interceptors (Angular 21)
In Angular 21, interceptors are plain functions - no class or implements HttpInterceptor needed. Register them with withInterceptors() in app.config.ts.
import { HttpInterceptorFn } from '@angular/common/http';
export const authInterceptor: HttpInterceptorFn = (req, next) => {
const token = localStorage.getItem('token');
if (token) {
const authReq = req.clone({
setHeaders: { Authorization: `Bearer ${token}` }
});
return next(authReq);
}
return next(req);
};
import { provideHttpClient, withInterceptors } from '@angular/common/http';
import { authInterceptor } from './auth.interceptor';
export const appConfig: ApplicationConfig = {
providers: [
provideHttpClient(withInterceptors([authInterceptor]))
]
};
Level Up Your Angular Skills
Master Angular with these hand-picked resources