Skip to content

Angular HttpClient

Angular's HttpClient is the built-in service for communicating with backend APIs over HTTP. This lesson covers setting it up and making basic typed requests.

What Is HttpClient?

HttpClient is an injectable Angular service, from @angular/common/http, that wraps the browser's fetch/XMLHttpRequest APIs with a consistent, Observable-based interface, request/response typing, interceptors, and testing utilities.

Every request returns an Observable that emits once (for a typical request/response) and completes, you subscribe to it (or, more often, combine it with the async pipe) to receive the result.

// app.config.ts
export const appConfig: ApplicationConfig = {
  providers: [provideHttpClient()],
};

// user.service.ts
@Injectable({ providedIn: 'root' })
export class UserService {
  private http = inject(HttpClient);

  getUsers() {
    return this.http.get<User[]>('/api/users');
  }
}

provideHttpClient() must be registered once in the application config before HttpClient can be injected anywhere.

Basic HTTP Methods

http.get<T>(url)
http.post<T>(url, body)
http.put<T>(url, body)
http.patch<T>(url, body)
http.delete<T>(url)
  • Every method accepts a generic type parameter for the expected response shape.
  • get/delete take a URL (and optional options); post/put/patch also take a request body.
  • All methods return an Observable, nothing happens until you subscribe (or pipe through async).
  • provideHttpClient() (or HttpClientModule in NgModule-based apps) must be registered before use.

HttpClient Cheatsheet

Common request patterns you will write constantly.

Task Example
Register HttpClient provideHttpClient() in app config
Inject the service private http = inject(HttpClient);
Typed GET request http.get<User[]>('/api/users')
POST with a body http.post<User>('/api/users', newUser)
Query parameters http.get(url, { params: { page: 1 } })
Custom headers http.get(url, { headers: { Authorization: token } })
Subscribe to a response obs$.subscribe(data => ...)
Use with async pipe {{ (users$ | async)?.length }}

Typing Requests and Responses

Passing a generic type argument to HttpClient methods gives you compile-time safety on the response shape, catching mismatched property names before they become runtime bugs.

interface User {
  id: string;
  name: string;
  email: string;
}

getUser(id: string) {
  return this.http.get<User>(`/api/users/${id}`);
}

Query Parameters and Headers

Query parameters and custom headers are passed through the options object on any HttpClient method, Angular encodes them correctly rather than requiring manual string concatenation.

this.http.get<Order[]>('/api/orders', {
  params: { status: 'shipped', page: 2 },
  headers: { 'X-Client-Version': '1.0' },
});

Rendering Responses With the Async Pipe

Rather than manually subscribing and storing data in a class property, exposing the request Observable directly and rendering it with the async pipe avoids manual subscription management entirely.

export class UserListComponent {
  private userService = inject(UserService);
  users$ = this.userService.getUsers();
}

<ul>
  @for (user of (users$ | async); track user.id) {
    <li>{{ user.name }}</li>
  }
</ul>

Common Mistakes

  • Forgetting to call .subscribe() (or use the async pipe), Observables from HttpClient do nothing until subscribed to.
  • Not registering provideHttpClient() before injecting HttpClient anywhere in the app.
  • Calling HttpClient methods directly from components instead of wrapping them in a dedicated service.
  • Manually building query strings instead of using the built-in params option.

Key Takeaways

  • HttpClient provides an Observable-based, typed interface for making HTTP requests.
  • provideHttpClient() must be registered once before the service can be injected anywhere.
  • Generic type parameters on request methods give compile-time safety for response shapes.
  • The async pipe is often the cleanest way to render HTTP responses without manual subscription code.

Pro Tip

Wrap every HttpClient call in a dedicated service method with a clear, typed return value; it keeps API details out of components and makes it trivial to swap in a mock service during testing.