← Back to Articles         
Query-String Parameters and HTTP Headers

Query-String Parameters and HTTP Headers

Published on 01 Oct 2026     8 min read Angular
HTTP & Web API Integration

Angular HttpClient: Query-String Parameters and HTTP Headers

Angular HttpClient allows you to send both query-string parameters and HTTP headers when calling an ASP.NET Core Web API.

For example:

GET /api/products?category=Laptop&page=1
Authorization: Bearer <token>

These serve different purposes:

Feature Purpose Example
Query parameters Pass filtering/search/paging values ?category=Laptop&page=1
HTTP headers Pass request metadata Authorization: Bearer token

Full Simple Sample Program

product.ts

export interface Product {
  id: number;
  name: string;
  price: number;
}

product.service.ts

This example demonstrates both query parameters and HTTP headers.

import { inject, Injectable } from '@angular/core';
import {
  HttpClient,
  HttpHeaders,
  HttpParams
} from '@angular/common/http';

import { Observable } from 'rxjs';
import { Product } from './product';

@Injectable({
  providedIn: 'root'
})
export class ProductService {

  private http = inject(HttpClient);

  private apiUrl =
    'https://localhost:7001/api/products';


  // Query-string parameters
  searchProducts(
    category: string,
    page: number
  ): Observable<Product[]> {

    const params = new HttpParams()
      .set('category', category)
      .set('page', page);

    return this.http.get<Product[]>(
      this.apiUrl,
      { params }
    );
  }


  // HTTP headers
  getProductsWithHeaders(): Observable<Product[]> {

    const headers = new HttpHeaders()
      .set('Authorization', 'Bearer sample-token')
      .set('X-Api-Key', '123456');

    return this.http.get<Product[]>(
      this.apiUrl,
      { headers }
    );
  }


  // Query parameters + headers
  searchProductsWithHeaders(
    category: string,
    page: number
  ): Observable<Product[]> {

    const params = new HttpParams()
      .set('category', category)
      .set('page', page);

    const headers = new HttpHeaders()
      .set('Authorization', 'Bearer sample-token')
      .set('X-Api-Key', '123456');

    return this.http.get<Product[]>(
      this.apiUrl,
      {
        params,
        headers
      }
    );
  }
}

1. How Do You Send Query-String Parameters?

What are Query-String Parameters?

Query-string parameters are values added to the end of a URL after ?.

For example:

https://localhost:7001/api/products?category=Laptop&page=1

Here:

category = Laptop
page     = 1

Multiple parameters are separated using:

&

Therefore:

?category=Laptop&page=1

Using HttpParams

Angular provides:

HttpParams

from:

import { HttpParams } from '@angular/common/http';

Create parameters:

const params = new HttpParams()
  .set('category', 'Laptop')
  .set('page', 1);

Then pass them to HttpClient:

return this.http.get<Product[]>(
  this.apiUrl,
  { params }
);

Angular constructs the URL appropriately:

GET /api/products?category=Laptop&page=1

Complete Query Parameter Method

searchProducts(
  category: string,
  page: number
): Observable<Product[]> {

  const params = new HttpParams()
    .set('category', category)
    .set('page', page);

  return this.http.get<Product[]>(
    this.apiUrl,
    { params }
  );
}

Call it:

this.productService
  .searchProducts('Laptop', 1)
  .subscribe({
    next: (products) => {
      console.log(products);
    }
  });

Angular sends:

GET https://localhost:7001/api/products?category=Laptop&page=1

ASP.NET Core Side

ASP.NET Core can receive these values using query binding:

[HttpGet]
public IActionResult GetProducts(
    [FromQuery] string category,
    [FromQuery] int page)
{
    return Ok(new
    {
        Category = category,
        Page = page
    });
}

So the complete flow is:

Angular
   ↓
HttpParams
   ↓
category = Laptop
page = 1
   ↓
HttpClient.get()
   ↓
GET /api/products?category=Laptop&page=1
   ↓
ASP.NET Core
   ↓
[FromQuery]
   ↓
category = "Laptop"
page = 1

Simpler Modern Syntax

For simple parameters, you don't always need to explicitly create HttpParams.

You can also write:

return this.http.get<Product[]>(
  this.apiUrl,
  {
    params: {
      category: 'Laptop',
      page: 1
    }
  }
);

This is convenient for simple cases.

For example:

searchProducts(
  category: string,
  page: number
): Observable<Product[]> {

  return this.http.get<Product[]>(
    this.apiUrl,
    {
      params: {
        category: category,
        page: page
      }
    }
  );
}

Or using shorthand:

searchProducts(
  category: string,
  page: number
): Observable<Product[]> {

  return this.http.get<Product[]>(
    this.apiUrl,
    {
      params: {
        category,
        page
      }
    }
  );
}

Both approaches are valid.


When Are Query Parameters Used?

Query parameters are commonly used for:

Searching
Filtering
Sorting
Pagination
Optional parameters

For example:

/api/products?search=laptop
/api/products?category=Electronics
/api/products?page=2&pageSize=20
/api/products?sortBy=price&sortOrder=desc

A real request might be:

GET /api/products
    ?search=laptop
    &category=Electronics
    &page=2
    &pageSize=20

2. How Do You Send HTTP Headers?

What are HTTP Headers?

HTTP headers contain additional metadata about an HTTP request.

For example:

Authorization: Bearer eyJhbGciOi...

or:

X-Api-Key: abc123

Headers are commonly used for:

Authentication
Authorization
API Keys
Content negotiation
Correlation IDs
Custom metadata

Using HttpHeaders

Angular provides:

HttpHeaders

Import it:

import { HttpHeaders } from '@angular/common/http';

Create headers:

const headers = new HttpHeaders()
  .set('Authorization', 'Bearer sample-token')
  .set('X-Api-Key', '123456');

Then pass them:

return this.http.get<Product[]>(
  this.apiUrl,
  { headers }
);

Complete Header Example

getProducts(): Observable<Product[]> {

  const headers = new HttpHeaders()
    .set(
      'Authorization',
      'Bearer sample-token'
    )
    .set(
      'X-Api-Key',
      '123456'
    );

  return this.http.get<Product[]>(
    this.apiUrl,
    { headers }
  );
}

The HTTP request conceptually becomes:

GET /api/products
Authorization: Bearer sample-token
X-Api-Key: 123456

ASP.NET Core Side

Suppose Angular sends:

X-Api-Key: 123456

ASP.NET Core can access it:

[HttpGet]
public IActionResult GetProducts()
{
    var apiKey =
        Request.Headers["X-Api-Key"].ToString();

    return Ok();
}

For a custom header, you can also bind it explicitly:

[HttpGet]
public IActionResult GetProducts(
    [FromHeader(Name = "X-Api-Key")] string apiKey)
{
    return Ok();
}

Flow:

Angular
   ↓
HttpHeaders
   ↓
X-Api-Key: 123456
   ↓
HTTP Request
   ↓
ASP.NET Core
   ↓
[FromHeader]
   ↓
apiKey = "123456"

Sending a JWT Token

One of the most common uses of HTTP headers is authentication.

Suppose you have:

const token = 'eyJhbGciOi...';

Create the header:

const headers = new HttpHeaders()
  .set(
    'Authorization',
    `Bearer ${token}`
  );

Then:

return this.http.get<Product[]>(
  this.apiUrl,
  { headers }
);

Request:

GET /api/products

Authorization: Bearer eyJhbGciOi...

ASP.NET Core authentication middleware can then validate the token.


Should We Add JWT Headers Manually Every Time?

Usually no.

Imagine you have 50 API methods:

getProducts()
getCategories()
getOrders()
getCustomers()
getUsers()
...

Repeating this everywhere:

const headers = new HttpHeaders()
  .set(
    'Authorization',
    `Bearer ${token}`
  );

would create duplicated code.

Instead, Angular commonly uses an HTTP interceptor.

Angular Service
      ↓
HttpClient
      ↓
Auth Interceptor
      ↓
Automatically adds JWT
      ↓
ASP.NET Core API

For example:

export const authInterceptor: HttpInterceptorFn =
  (req, next) => {

    const token = 'sample-token';

    const newRequest = req.clone({
      setHeaders: {
        Authorization: `Bearer ${token}`
      }
    });

    return next(newRequest);
  };

Then configure it:

provideHttpClient(
  withInterceptors([
    authInterceptor
  ])
)

We'll normally use this approach for authentication headers in a real application.


Sending Query Parameters and Headers Together

You can send both in the same request.

searchProducts(
  category: string,
  page: number
): Observable<Product[]> {

  const params = new HttpParams()
    .set('category', category)
    .set('page', page);

  const headers = new HttpHeaders()
    .set(
      'Authorization',
      'Bearer sample-token'
    );

  return this.http.get<Product[]>(
    this.apiUrl,
    {
      params,
      headers
    }
  );
}

The request becomes:

GET /api/products?category=Laptop&page=1
Authorization: Bearer sample-token

Notice where each value goes:

URL
 ↓
/api/products?category=Laptop&page=1
              └───────────────┘
                Query Params


HTTP Headers
 ↓
Authorization: Bearer sample-token

Query Parameters vs Headers

This distinction is important for interviews.

Query Parameters HTTP Headers
Part of URL Part of HTTP metadata
Visible in URL Not part of URL
Filtering Authentication
Searching JWT
Sorting API keys
Pagination Correlation IDs
HttpParams HttpHeaders
ASP.NET [FromQuery] ASP.NET [FromHeader]

For example:

Filtering
    ↓
?category=Laptop

Pagination
    ↓
?page=2&pageSize=20

Whereas:

JWT
    ↓
Authorization: Bearer token

API Key
    ↓
X-Api-Key: 123456

Important: HttpParams and HttpHeaders Are Immutable

This is a useful Angular interview point.

Don't do this:

let params = new HttpParams();

params.set('category', 'Laptop');
params.set('page', 1);

set() returns a new HttpParams instance.

So use:

let params = new HttpParams();

params = params.set('category', 'Laptop');
params = params.set('page', 1);

Or, more commonly:

const params = new HttpParams()
  .set('category', 'Laptop')
  .set('page', 1);

The same concept applies to HttpHeaders.


Key Points

  • Query parameters are passed through the params option.
this.http.get(url, { params });
  • Angular provides HttpParams for constructing query parameters.
const params = new HttpParams()
  .set('category', 'Laptop')
  .set('page', 1);
  • HTTP headers are passed through the headers option.
this.http.get(url, { headers });
  • Angular provides HttpHeaders.
const headers = new HttpHeaders()
  .set('X-Api-Key', '123456');
  • You can send both together:
this.http.get(url, {
  params,
  headers
});
  • Query parameters are commonly used for searching, filtering, sorting and pagination.
  • Headers are commonly used for JWT tokens, API keys, correlation IDs and other request metadata.
  • HttpParams and HttpHeaders are immutable.
  • For JWT authentication, prefer an HTTP interceptor rather than manually adding the header to every request.

Interview Questions and Answers

1. How do you send query-string parameters using Angular HttpClient?

Use the params option, commonly with HttpParams.

const params = new HttpParams()
  .set('category', 'Laptop')
  .set('page', 1);

return this.http.get<Product[]>(
  this.apiUrl,
  { params }
);

This generates a URL such as:

/api/products?category=Laptop&page=1

2. How do you send HTTP headers?

Use the headers option with HttpHeaders.

const headers = new HttpHeaders()
  .set('X-Api-Key', '123456');

return this.http.get<Product[]>(
  this.apiUrl,
  { headers }
);

3. How does ASP.NET Core receive query parameters?

Using query binding:

[FromQuery] string category

For example:

public IActionResult Get(
    [FromQuery] string category)

4. How does ASP.NET Core receive custom headers?

Using:

[FromHeader]

For example:

[FromHeader(Name = "X-Api-Key")]
string apiKey

5. What is the difference between query parameters and HTTP headers?

Query parameters are part of the URL and normally describe what data you want, such as filtering, searching or pagination.

Headers contain request metadata, such as authentication tokens, API keys and correlation IDs.


6. How do you send both parameters and headers?

return this.http.get<Product[]>(
  this.apiUrl,
  {
    params,
    headers
  }
);

7. Should JWT headers be added manually to every request?

Usually no. An Angular HTTP interceptor is normally used to automatically attach the access token to applicable outgoing requests.


Short Interview Answer

In Angular, query-string parameters are sent through the params option, commonly using HttpParams, while HTTP headers are sent through the headers option using HttpHeaders. Query parameters are typically used for filtering, searching and pagination, whereas headers are commonly used for authentication, API keys and other request metadata.

← Back to Articles