This content originally appeared on Telerik Blogs and was authored by Dhananjay Kumar
Angular v20 brings us the httpResource API, built on top of the HttpClient so interceptors and testing tools work better than with the Resource API.
Angular 19 introduced the Resource API for the following purposes:
- Fetch data from the API
- Update data locally
- Asynchronously load a local resource
It should not be used for mutation, such as POST operations. Read more about the resource API here.
However, there was an issue when working with the Resource API. One major problem was that it wasn’t built on top of HttpClient, which meant that interceptors did not function as expected.
To address the above problem, Angular 20 introduces the httpResource API.
The httpResource extends the Resource API by using the HttpClient under the hood, providing a seamless way to make HTTP requests while supporting interceptors and existing testing tools.
- httpResource is built on top of the resource primitive.
- It uses HttpClient as its loader.
- It serves as an abstraction for @angular/common/http.
- It makes HTTP requests through Angular’s HTTP stack.
- It works with interceptors.
You can fetch data using the httpResource API as shown below:
export class App {
constructor() {
effect(() => {
console.log('products', this.products.value());
})
}
products = httpResource<IProduct[]>(() => `http://localhost:3000/product`);
}
You can use products to render a table on the template as shown below.
<table>
<tr>
<th>ID</th>
<th>Name</th>
<th>Price</th>
</tr>
@for(p of products.value(); track p.id) {
<tr>
<td>{{ p.id }}</td>
<td>{{ p.name }}</td>
<td>{{ p.price }}</td>
<td>{{ p.category }}</td>
<td>{{ p.description }}</td>
</tr>
}
</table>
Working with Interceptors
The httpResource API is built on top of the @angular/common/http stack. Any HTTP request made through it will be intercepted by the application’s HTTP interceptor. For example, if you have an interceptor defined like the one below:
import { HttpInterceptorFn } from '@angular/common/http';
export const appInterceptor: HttpInterceptorFn = (req, next) => {
console.log('Request made with URL:', req.url);
return next(req);
};
It should show the output in the browser for the data fetched using the httpResource API. Request made with URL: http://localhost:3000/product.
Schema Validation
By default, the httpResource performs a GET request and returns an unknown
typed JSON response.
- By default, it performs a GET operation.
- It expects JSON type data as the response.
- The type of response data is unknown.
When using the httpResource API, it’s essential to validate the schema to verify that the received data matches the expected structure. To achieve this, the httpResource API allows the use of schema validation libraries, such as Zod.
To use Zod with the httpResource API, first install it and then import it.
import { z } from 'zod';
After importing, create a schema for the product as shown in the example below.
IProductSchema = z.object({
id: z.number(),
name: z.string(),
price: z.number(),
category: z.string(),
description: z.string().optional()
});
ProductResultsSchema = z.array(this.IProductSchema);
First, we define a schema for the product object, and then the array of products using this schema.
After defining the schema, you can use it to parse the response from the httpResource, as shown below.
products = httpResource(() => ({
url: `http://localhost:3000/product`,
method: 'GET'
}), {
parse: (data) => this.ProductResultsSchema.parse(data)
});
Default Value
The httpResource API supports a default value. This value is returned when the resource is in one of the following states.
- Idle
- Error
- Loading
If the default value is not specified, its value is set to undefined. You can set the default value as shown below.
products = httpResource(() => ({
url: `http://localhost:3000/product`,
method: 'GET'
}), {
defaultValue: [
{ id: 0, name: 'default', price: 0, category: 'default', description: 'default' },
],
parse: (data) => this.ProductResultsSchema.parse(data)
});
The httpResource and HttpClient
The key difference between httpResource and HttpClient lies in their request behavior:
- httpResource is eager – It triggers the HTTP request immediately as soon as it is defined.
- HttpClient is lazy – It only initiates a request when the returned observable is subscribed to.
Each new request made with the httpResource API automatically cancels the previous one. Because of this behavior, it is not suitable for mutations and should be used only for data fetching.
product = httpResource<IProduct>(() => ({
url: `http://localhost:3000/product/${this.searchId()}`,
method: 'GET'
}));
Making an Advanced Request
The httpResource API supports a request object. An httpResource request sent to the backend can include several fields. Among them, only the url
is required—all other fields are optional.
- url
- method
- body
- params
- headers
- context
- reportProgress
- withCredentials
- transferCache
Although the httpResource object supports other verbs, such as POST, PUT, DELETE, etc., it is advisable to use the httpResource API only to fetch data from the backend and not to perform any mutations using other HTTP verbs.
You can pass the httpResource object with value for various properties as shown below:
product = httpResource<IProduct>(() => ({
url: `http://localhost:3000/product/${this.searchId()}`,
method: 'GET',
headers: {
'X-Special': 'true',
},
params: {
'fast': 'yes',
},
reportProgress: true,
withCredentials: true,
transferCache: true,
}));
Returned Signals
Like the Resource API, the htppResource API returns a WritableResource
and has read-only properties such as:
- Value
- Status
- Error
- isLoading
All of them are signal types, which means you can track them inside an effect. Besides the above signals, it also returns metadata about the response.
- headers
- statusCode
- progress
constructor() {
effect(() => {
console.log('products', this.products.value());
console.log('products error', this.products.error()?.message);
console.log('products satus', this.products.status());
})
}
Other Response Type
The httpResource API has dedicated methods to work with other response types. They are as follows.
httpResource.text
returns plain texthttpResource.blob
returns the data as a BlobhttpResource.arrayBuffer
returns the data as an ArrayBuffer
You can download an image using the httpResource API as shown below:
@Injectable({
providedIn: 'root'
})
export class Product {
getImage(): HttpResourceRef<Blob | undefined> {
return httpResource.blob(() => ({
url: "http://localhost:3000/product/image",
method: 'GET',
reportProgress: true,
}));
}
}
Summary
The httpResource API is one of the most exciting features of Angular V20, and you must use it to fetch data from the backend. It uses the HttpClient as a loader and returns various responses as signal. You should avoid using it for data mutation at the backend.
I hope you find this post helpful. Thanks for reading.
This content originally appeared on Telerik Blogs and was authored by Dhananjay Kumar

Dhananjay Kumar | Sciencx (2025-06-09T11:31:17+00:00) Getting Started with the httpResource API in Angular. Retrieved from https://www.scien.cx/2025/06/09/getting-started-with-the-httpresource-api-in-angular/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.