571

I'm trying to use the newFetch API:

I am making aGET request like this:

var request = new Request({  url: 'http://myapi.com/orders',  method: 'GET'});fetch(request);

However, I'm unsure how to add a query string to theGET request. Ideally, I want to be able to make aGET request to aURL like:

'http://myapi.com/orders?order_id=1'

InjQuery I could do this by passing{order_id: 1} as thedata parameter of$.ajax(). Is there an equivalent way to do that with the newFetch API?

Arsen Khachaturyan's user avatar
Arsen Khachaturyan
8,4304 gold badges46 silver badges47 bronze badges
askedJan 27, 2016 at 13:36
mylescc's user avatar
0

14 Answers14

903

A concise, modern approach:

fetch('https://example.com?' + new URLSearchParams({    foo: 'value',    bar: 2,}).toString())

How it works:URLSearchParams toString() method will convert the URLSearchParams instance into a string representation, which happens to be a properly encoded query string.

It is also legal to leave out the.toString() call like so:fetch('https://...' + new URLSearchParams(...)). JavaScript automatically calls.toString() when an object is concatenated with a string. This does require future code readers to have a deeper understanding of the language to understand your code.

A complete example of a fetch request with query parameters:

// Real example you can copy-paste and play with.// jsonplaceholder.typicode.com provides a dummy rest-api// for this sort of purpose.async function doAsyncTask() {  const url = (    'https://jsonplaceholder.typicode.com/comments?' +    new URLSearchParams({ postId: 1 }).toString()  );  const result = await fetch(url)    .then(response => response.json());  console.log('Fetched from: ' + url);  console.log(result);}doAsyncTask();


If you are using/supporting...

  • IE: Internet Explorer does not provide native support for URLSearchParams or fetch, but there arepolyfillsavailable.

  • Node: As of Node 18 there is native support for the fetch API (in version 17.5 it was behind the--experimental-fetch flag). In older versions, you can add the fetch API through a package likenode-fetch. URLSearchParams comes with Node, and can be found as a global object since version 10. In older version you can find it atrequire('url').URLSearchParams.

  • TypeScript: The values provided toURLSearchParams will be auto-coerced into a string, which is why TypeScript's definition forURLSearchParams requires you to provide all values as strings. Those who don't use TypeScript may be comfortable providing other value types to this function if they feel the coercion behavior is intuitive. For examples, numbers will behave exactly as you would expect, while the way arrays get implicitly coerced may cause confusion to future readers.

  • TypeScript v4 or older with Node: Older versions of TypeScript did not offer type definitions for the global URLSearchParams in the Node environment. The simplest workaround is to just import it from theurl module. This later got resolved at some point during v4 (I'm not sure what the exact version is that fixes this). Seethis issue for more info.

answeredOct 17, 2019 at 17:30
Scotty Jamison's user avatar
Sign up to request clarification or add additional context in comments.

9 Comments

Thanks for sharing. I think this should be accepted answer. The asked to pass parameters to the fetch API, and although that isn't possible, this answer is pretty bloody close to what that would look like in structure.
This doesn't appear to correctly handle multiple values for the same key. I was expecting to be able to writenew URLSearchParams({foo: ['bar', 'baz']}) but rather thanfoo=bar&foo=baz it gets escaped asfoo=bar%Cbaz
@jymbob to have multiple values, you'll have to use the .append() method on URLSearchParams. e.g.s = new URLSearchParams({foo: 'bar'}); s.append('foo', 'baz'); s.toString(). Alternativly, the constructor can take a list of lists instead of an object.new URLSearchParams([['foo', 'bar'], ['foo', 'baz']]).toString() See the docs page for more usage info:developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
An even more concise approach would be to use string interpolation: ```https://example.com?${new URLSearchParams({foo: 'value'})} ```developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Be aware that when using typescript you have to use strings as values only. Sobar: 2 should bebar: '2'.
|
370

Update March 2017:

URL.searchParams support has officially landed in Chrome 51, but other browsers still require apolyfill.


Theofficial way to work with query parameters is just to add them onto the URL. Fromthe spec, this is an example:

var url = new URL("https://geo.example.org/api"),    params = {lat:35.696233, long:139.570431}Object.keys(params).forEach(key => url.searchParams.append(key, params[key]))fetch(url).then(/* … */)

However, I'm not sure Chrome supports thesearchParams property of a URL (at the time of writing) so you might want to either use athird party library orroll-your-own solution.

Update April 2018:

With the use ofURLSearchParams constructor you could assign a 2D array or a object and just assign that to theurl.search instead of looping over all keys and append them

var url = new URL('https://sl.se')var params = {lat:35.696233, long:139.570431} // or:var params = [['lat', '35.696233'], ['long', '139.570431']]url.search = new URLSearchParams(params).toString();fetch(url)

Sidenote:URLSearchParams is also available in NodeJS

const { URL, URLSearchParams } = require('url');
answeredJan 27, 2016 at 13:50
CodingIntrigue's user avatar

13 Comments

There's alsodeveloper.mozilla.org/en-US/docs/Web/API/URLSearchParams/…, tho as of this writing it's still making its way through spec, and not well-supported yet. And the API is more like Java than JS. :/
Seecaniuse.com/#feat=urlsearchparams for support for theURLSearchParams interface; I wouldassume (though I'm not 100% certain) that the browsers in red there are exactly the browsers for whichURL objects will not have the.searchParams property. Importantly, Edge still does not have support.
From the documentation: "Note that using a URLSearchParams instance is deprecated; soon browsers will just use a USVString for the init." source:developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/…
new URLSearchParams doesn't seem to work correctly withArray properties. I expected it to convert the propertyarray: [1, 2] toarray[]=1&array[]=2, but converted it toarray=1,2. Manually using theappend method of it does result inarray=1&array=2, but I would have to iterate over params object, and do that only for array types, not very ergonomic.
It was indeed added in error :)github.com/mdn/sprints/issues/2856
|
51
let params = {  "param1": "value1",  "param2": "value2"};let query = Object.keys(params)             .map(k => encodeURIComponent(k) + '=' + encodeURIComponent(params[k]))             .join('&');let url = 'https://example.com/search?' + query;fetch(url)  .then(data => data.text())  .then((text) => {    console.log('request succeeded with JSON response', text)  }).catch(function (error) {    console.log('request failed', error)  });
answeredFeb 6, 2017 at 22:19
Sudharshan's user avatar

4 Comments

do you need to encode the key? i've never done that.
@chovy - you do if your key contains special characters, like "&". Most of the time it won't, but sometimes it can.
NOTE: encodeURIComponent can give bad results, e.g. it'll incorrectly encode a space as "%20" instead of "+" - this behavior is fine when you're percent encoding, for example, a URL's path (an intended use case), but query parameters are generally form-encoded, which follows an older version of the percent-encoding specification - you can useURLSearchParams() to properly encode/decode query parameters. Seethis S.O. question to learn more.
I rectract my previous comment. I've since learned that after the?, there's two allowed ways to encode a space, both%20 and+ are acceptable. So while bothURLSearchParams() andencodeURIComponent() will give out different results, a server is supposed to be able to accept either.
35

As already answered, this is per spec not possible with thefetch-API, yet. But I have to note:

If you are onnode, there's thequerystring package. It can stringify/parse objects/querystrings:

var querystring = require('querystring')var data = { key: 'value' }querystring.stringify(data) // => 'key=value'

...then just append it to the url to request.


However, the problem with the above is, that you always have to prepend a question mark (?). So, another way is to use theparse method from nodesurl package and do it as follows:

var url = require('url')var data = { key: 'value' }url.format({ query: data }) // => '?key=value'

Seequery athttps://nodejs.org/api/url.html#url_url_format_urlobj

This is possible, as it does internally justthis:

search = obj.search || (    obj.query && ('?' + (        typeof(obj.query) === 'object' ?        querystring.stringify(obj.query) :        String(obj.query)    ))) || ''
answeredFeb 18, 2016 at 20:17
yckart's user avatar

Comments

22

You can set params on yourURL'ssearchParams:

const url = new URL('http://myapi.com/orders');url.searchParams.set('order_id', '1');fetch(url);

This has the advantage of building a request explicitly while allowing the originalURL to be in any valid format.

answeredMar 14, 2023 at 14:04
Nicky McCurdy's user avatar

4 Comments

I tested it in Firefox before making my comment and it didn’t work.
Here is alive demo on JSBin in which I replacefetch withconsole.log. It logs the original URL from line one without the query string you attempt to add on line two when I test in Firefox, Safari, or Chrome.
For multiple query params const searchParams = new URLSearchParams({ one : '1' , two : '2' }); const url = new URL(${process.env.API_URL}/messages?${searchParams.toString()}); fetch(url);
For me it worked fine using Chrome 124.0.6367.118 and Firefox 125.0 (tested on Linux).
14

You can usestringify fromquery-string.

import { stringify } from 'query-string';fetch(`https://example.org?${stringify(params)}`)
Sebastian Simon's user avatar
Sebastian Simon
19.8k8 gold badges61 silver badges88 bronze badges
answeredJun 30, 2018 at 13:46
Hirurg103's user avatar

Comments

10

encodeQueryString — encode an object as querystring parameters

/** * Encode an object as url query string parameters * - includes the leading "?" prefix * - example input — {key: "value", alpha: "beta"} * - example output — output "?key=value&alpha=beta" * - returns empty string when given an empty object */function encodeQueryString(params) {    const keys = Object.keys(params)    return keys.length        ? "?" + keys            .map(key => encodeURIComponent(key)                + "=" + encodeURIComponent(params[key]))            .join("&")        : ""}encodeQueryString({key: "value", alpha: "beta"}) //> "?key=value&alpha=beta"
answeredMar 16, 2018 at 21:32
ChaseMoskal's user avatar

Comments

8

I know this is stating the absolute obvious, but I feel it's worth adding this as an answer as it's the simplest of all:

const orderId = 1;fetch('http://myapi.com/orders?order_id=' + orderId);
answeredApr 19, 2017 at 2:35
Evert's user avatar

3 Comments

It's worth qualifying that this only works reliably with integer types. If you use strings, especially user-supplied ones (like search criteria) then you have to escape the string, otherwise you can get odd results if characters like/,+ or& appear in the string.
Using the Request object can help, especially if you want to use a function to build the request and then hand that to the fetch() call, but I don't think using it is "absolute obvious". Also, the url should not be specified in the object literal of config options; it should be passed separately as the 1st parameter to the Request constructor (developer.mozilla.org/en-US/docs/Web/API/Request/Request).
@Gen1-1, ty. Made some edits. My sample was based on OP's snippet, but I simplified it a bit.
5

Solution without external packages

to perform aGET request using the fetch api I worked on this solution that doesn't require the installation of packages.

this is an example of a call to the google's map api

// encode to scape spacesconst esc = encodeURIComponent;const url = 'https://maps.googleapis.com/maps/api/geocode/json?';const params = {     key: "asdkfñlaskdGE",    address: "evergreen avenue",    city: "New York"};// this line takes the params object and builds the query stringconst query = Object.keys(params).map(k => `${esc(k)}=${esc(params[k])}`).join('&')const res = await fetch(url+query);const googleResponse = await res.json()

feel free to copy this code and paste it on the console to see how it works!!

the generated url is something like:

https://maps.googleapis.com/maps/api/geocode/json?key=asdkf%C3%B1laskdGE&address=evergreen%20avenue&city=New%20York

this is what I was looking before I decided to write this, enjoy :D

answeredSep 24, 2020 at 2:46
Carlos's user avatar

3 Comments

Thanks Carlos. I forgot to escape the query params.
What’s the point ofconst esc = encodeURIComponent except making the code harder to read?
5

I like to use the URL API in such cases

const url = new URL('http://myapi.com/orders');url.searchParams.append('sort', 'date');url.searchParams.append('order', 'desc');fetch(url.href);

https://developer.mozilla.org/en-US/docs/Web/API/URL

answeredNov 27, 2024 at 19:34
schaenk's user avatar

Comments

4

Maybe this is better:

const withQuery = require('with-query');fetch(withQuery('https://api.github.com/search/repositories', {  q: 'query',  sort: 'stars',  order: 'asc',})).then(res => res.json()).then((json) => {  console.info(json);}).catch((err) => {  console.error(err);});
answeredMar 30, 2017 at 8:24
Bin HOU's user avatar

Comments

1

Template literals are also a valid option here, and provide a few benefits.

You can include raw strings, numbers, boolean values, etc:

    let request = new Request(`https://example.com/?name=${'Patrick'}&number=${1}`);

You can include variables:

    let request = new Request(`https://example.com/?name=${nameParam}`);

You can include logic and functions:

    let request = new Request(`https://example.com/?name=${nameParam !== undefined ? nameParam : getDefaultName() }`);

As far as structuring the data of a larger query string, I like using an array concatenated to a string. I find it easier to understand than some of the other methods:

let queryString = [  `param1=${getParam(1)}`,  `param2=${getParam(2)}`,  `param3=${getParam(3)}`,].join('&');let request = new Request(`https://example.com/?${queryString}`, {  method: 'GET'});
answeredSep 29, 2017 at 20:07
Pat Kearns's user avatar

1 Comment

You have to be very careful with this method because it does not URL-escape the strings first. So if you get a variable that contains a character like+ or& then it won't work as expected and you'll end up with different parameters and values to what you thought.
0
const query = {    is_active: true,};let url = `${apiUrl}/<endPoint>`;const searchParams = Object.keys(query).length ? new URLSearchParams(query).toString() : null;if (searchParams) {url = `${url}?${searchParams}`}

for nextJs 13+

const response = await fetch(url, {  method: "GET",  next: {    // revalidate will be after 4 min    revalidate: 240,  },  // cache: "no-cache",});
answeredJul 4, 2023 at 7:23
Md Wahiduzzaman Emon's user avatar

Comments

-1

Was just working with Nativescript's fetchModule and figured out my own solution using string manipulation.Append the query string bit by bit to the url. Here is an example where query is passed as a json object (query = {order_id: 1}):

function performGetHttpRequest(fetchLink='http://myapi.com/orders', query=null) {    if(query) {        fetchLink += '?';        let count = 0;        const queryLength = Object.keys(query).length;        for(let key in query) {            fetchLink += key+'='+query[key];            fetchLink += (count < queryLength) ? '&' : '';            count++;        }    }    // link becomes: 'http://myapi.com/orders?order_id=1'    // Then, use fetch as in MDN and simply pass this fetchLink as the url.}

I tested this over a multiple number of query parameters and it worked like a charm :)Hope this helps someone.

answeredJan 10, 2020 at 22:34
Amjad Abujamous's user avatar

3 Comments

This is a good example of why you should use 3rd party libs - your code might be working fine, but someone already did it much better
This has the same drawbacks asthe answer by Evert andthe one by Pat Kearns already provided more than two years earlier.“I tested this over a multiple number of query parameters and it worked like a charm” — You didn’t test this with anything relevant, then.URLs have a syntax that can be tokenized on specific characters. Trying any of these characters in your function should make it obvious that this code is broken.
@SebastianSimon Two years later, I stand corrected. Thank you my friend.
Protected question. To answer this question, you need to have at least 10 reputation on this site (not counting theassociation bonus). The reputation requirement helps protect this question from spam and non-answer activity.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.