How to force Angular2 to POST using x-www-form-urlencoded

For Angular > 4.3 (New HTTPClient) use the following:

let body = new URLSearchParams();
body.set('user', username);
body.set('password', password);

let options = {
    headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded')
};

this.http
    .post('//yourUrl.com/login', body.toString(), options)
    .subscribe(response => {
        //...
    });

Note 3 things to make it work as expected:

  1. Use URLSearchParams for your body
  2. Convert body to string
  3. Set the header's content-type

Attention: Older browsers do need a polyfill! I used: npm i url-search-params-polyfill --save and then added to polyfills.ts: import 'url-search-params-polyfill';


UPDATE June 2020: This answer is 4 years old and no longer valid due to API changes in Angular. Please refer to more recent answers for the current version approach.


You can do this using URLSearchParams as the body of the request and angular will automatically set the content type to application/x-www-form-urlencoded and encode the body properly.

let body = new URLSearchParams();
body.set('username', username);
body.set('password', password);

this.http.post(this.loginUrl, body).map(...);

The reason it's not currently working for you is you're not encoding the body data in the correct format and you're not setting the header options correctly.

You need to encode the body like this:

let body = `username=${username}&password=${password}`;

You need to set the header options like this:

this.http.post(this.loginUrl, body, { headers: headers }).map(...);

For those still looking for an answer this is how I solved it with Angular 5 and HttpClient:

const formData = new FormData();

// append your data
formData.append('myKey1', 'some value 1');
formData.append('myKey1', 'some value 2');
formData.append('myKey3', true);

this.httpClient.post('apiPath', formData);

Do NOT set Content-Type header, angular will fix this for you!


This is what worked for me with Angular 7:

const payload = new HttpParams()
  .set('username', username)
  .set('password', password);

this.http.post(url, payload);

No need to explicitly set the header with this approach.

Note that the HttpParams object is immutable. So doing something like the following won't work, it will give you an empty body:

const payload = new HttpParams();
payload.set('username', username);
payload.set('password', password);

this.http.post(url, payload);