{"doc":{"body":[{"type":"prose","value":{"id":null,"title":null,"isH3":false,"content":"<p>The <a href=\"/en-US/docs/Web/API/Fetch_API\">Fetch API</a> provides a JavaScript interface for making HTTP requests and processing the responses.</p>\n<p>Fetch is the modern replacement for <a href=\"/en-US/docs/Web/API/XMLHttpRequest\"><code>XMLHttpRequest</code></a>: unlike <code>XMLHttpRequest</code>, which uses callbacks, Fetch is promise-based and is integrated with features of the modern web such as <a href=\"/en-US/docs/Web/API/Service_Worker_API\">service workers</a> and <a href=\"/en-US/docs/Web/HTTP/Guides/CORS\">Cross-Origin Resource Sharing (CORS)</a>.</p>\n<p>With the Fetch API, you make a request by calling <a href=\"/en-US/docs/Web/API/Window/fetch\" title=\"fetch()\"><code>fetch()</code></a>, which is available as a global function in both <a href=\"/en-US/docs/Web/API/Window\" title=\"window\"><code>window</code></a> and <a href=\"/en-US/docs/Web/API/WorkerGlobalScope\" title=\"worker\"><code>worker</code></a> contexts. You pass it a <a href=\"/en-US/docs/Web/API/Request\"><code>Request</code></a> object or a string containing the URL to fetch, along with an optional argument to configure the request.</p>\n<p>The <code>fetch()</code> function returns a <a href=\"/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\"><code>Promise</code></a> which is fulfilled with a <a href=\"/en-US/docs/Web/API/Response\"><code>Response</code></a> object representing the server's response. You can then check the request status and extract the body of the response in various formats, including text and JSON, by calling the appropriate method on the response.</p>\n<p>Here's a minimal function that uses <code>fetch()</code> to retrieve some JSON data from a server:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>async function getData() {\n  const url = \"https://example.org/products.json\";\n  try {\n    const response = await fetch(url);\n    if (!response.ok) {\n      throw new Error(`Response status: ${response.status}`);\n    }\n\n    const result = await response.json();\n    console.log(result);\n  } catch (error) {\n    console.error(error.message);\n  }\n}\n</code></pre></div>\n<p>We declare a string containing the URL and then call <code>fetch()</code>, passing the URL with no extra options.</p>\n<p>The <code>fetch()</code> function will reject the promise on some errors, but not if the server responds with an error status like <a href=\"/en-US/docs/Web/HTTP/Reference/Status/404\"><code>404</code></a>: so we also check the response status and throw if it is not OK.</p>\n<p>Otherwise, we fetch the response body content as <a href=\"/en-US/docs/Glossary/JSON\">JSON</a> by calling the <a href=\"/en-US/docs/Web/API/Response/json\" title=\"json()\"><code>json()</code></a> method of <code>Response</code>, and log one of its values. Note that like <code>fetch()</code> itself, <code>json()</code> is asynchronous, as are all the other methods to access the response body content.</p>\n<p>In the rest of this page we'll look in more detail at the different stages of this process.</p>"}},{"type":"prose","value":{"id":"making_a_request","title":"Making a request","isH3":false,"content":"<p>To make a request, call <code>fetch()</code>, passing in:</p>\n<ol>\n<li>a definition of the resource to fetch. This can be any one of:\n<ul>\n<li>a string containing the URL</li>\n<li>an object, such as an instance of <a href=\"/en-US/docs/Web/API/URL\"><code>URL</code></a>, which has a <a href=\"/en-US/docs/Glossary/Stringifier\">stringifier</a> that produces a string containing the URL</li>\n<li>a <a href=\"/en-US/docs/Web/API/Request\"><code>Request</code></a> instance</li>\n</ul>\n</li>\n<li>optionally, an object containing options to configure the request.</li>\n</ol>\n<p>In this section we'll look at some of the most commonly-used options. To read about all the options that can be given, see the <a href=\"/en-US/docs/Web/API/Window/fetch\"><code>fetch()</code></a> reference page.</p>"}},{"type":"prose","value":{"id":"setting_the_method","title":"Setting the method","isH3":true,"content":"<p>By default, <code>fetch()</code> makes a <a href=\"/en-US/docs/Web/HTTP/Reference/Methods/GET\"><code>GET</code></a> request, but you can use the <code>method</code> option to use a different <a href=\"/en-US/docs/Web/HTTP/Reference/Methods\">request method</a>:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>const response = await fetch(\"https://example.org/post\", {\n  method: \"POST\",\n  // …\n});\n</code></pre></div>\n<p>If the <code>mode</code> option is set to <code>no-cors</code>, then <code>method</code> must be one of <code>GET</code>, <code>POST</code> or <code>HEAD</code>.</p>"}},{"type":"prose","value":{"id":"setting_a_body","title":"Setting a body","isH3":true,"content":"<p>The request body is the payload of the request: it's the thing the client is sending to the server. You cannot include a body with <code>GET</code> requests, but it's useful for requests that send content to the server, such as <a href=\"/en-US/docs/Web/HTTP/Reference/Methods/POST\"><code>POST</code></a> or <a href=\"/en-US/docs/Web/HTTP/Reference/Methods/PUT\"><code>PUT</code></a> requests. For example, if you want to upload a file to the server, you might make a <code>POST</code> request and include the file as the request body.</p>\n<p>To set a request body, pass it as the <code>body</code> option:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>const response = await fetch(\"https://example.org/post\", {\n  method: \"POST\",\n  body: JSON.stringify({ username: \"example\" }),\n  // …\n});\n</code></pre></div>\n<p>You can supply the body as an instance of any of the following types:</p>\n<ul>\n<li>a string</li>\n<li><a href=\"/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer\"><code>ArrayBuffer</code></a></li>\n<li><a href=\"/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray\"><code>TypedArray</code></a></li>\n<li><a href=\"/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView\"><code>DataView</code></a></li>\n<li><a href=\"/en-US/docs/Web/API/Blob\"><code>Blob</code></a></li>\n<li><a href=\"/en-US/docs/Web/API/File\"><code>File</code></a></li>\n<li><a href=\"/en-US/docs/Web/API/URLSearchParams\"><code>URLSearchParams</code></a></li>\n<li><a href=\"/en-US/docs/Web/API/FormData\"><code>FormData</code></a></li>\n<li><a href=\"/en-US/docs/Web/API/ReadableStream\"><code>ReadableStream</code></a></li>\n</ul>\n<p>Other objects are converted to strings using their <code>toString()</code> method. For example, you can use a <a href=\"/en-US/docs/Web/API/URLSearchParams\"><code>URLSearchParams</code></a> object to encode form data (see <a href=\"#setting_headers\">setting headers</a> for more information):</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>const response = await fetch(\"https://example.org/post\", {\n  method: \"POST\",\n  headers: {\n    \"Content-Type\": \"application/x-www-form-urlencoded\",\n  },\n  // Automatically converted to \"username=example&amp;password=password\"\n  body: new URLSearchParams({ username: \"example\", password: \"password\" }),\n  // …\n});\n</code></pre></div>\n<p>Note that just like response bodies, request bodies are streams, and making the request reads the stream, so if a request contains a body, you can't make it twice:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js example-bad notranslate\"><code>const request = new Request(\"https://example.org/post\", {\n  method: \"POST\",\n  body: JSON.stringify({ username: \"example\" }),\n});\n\nconst response1 = await fetch(request);\nconsole.log(response1.status);\n\n// Will throw: \"Body has already been consumed.\"\nconst response2 = await fetch(request);\nconsole.log(response2.status);\n</code></pre></div>\n<p>Instead, you would need to <a href=\"/en-US/docs/Web/API/Request/clone\" title=\"create a clone\">create a clone</a> of the request before sending it:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>const request1 = new Request(\"https://example.org/post\", {\n  method: \"POST\",\n  body: JSON.stringify({ username: \"example\" }),\n});\n\nconst request2 = request1.clone();\n\nconst response1 = await fetch(request1);\nconsole.log(response1.status);\n\nconst response2 = await fetch(request2);\nconsole.log(response2.status);\n</code></pre></div>\n<p>See <a href=\"#locked_and_disturbed_streams\">Locked and disturbed streams</a> for more information.</p>"}},{"type":"prose","value":{"id":"setting_headers","title":"Setting headers","isH3":true,"content":"<p>Request headers give the server information about the request: for example, in a <code>POST</code> request, the <a href=\"/en-US/docs/Web/HTTP/Reference/Headers/Content-Type\"><code>Content-Type</code></a> header tells the server the format of the request's body.</p>\n<p>To set request headers, assign them to the <code>headers</code> option.</p>\n<p>You can pass an object literal here containing <code>header-name: header-value</code> properties:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>const response = await fetch(\"https://example.org/post\", {\n  method: \"POST\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ username: \"example\" }),\n  // …\n});\n</code></pre></div>\n<p>Alternatively, you can construct a <a href=\"/en-US/docs/Web/API/Headers\"><code>Headers</code></a> object, add headers to that object using <a href=\"/en-US/docs/Web/API/Headers/append\"><code>Headers.append()</code></a>, then assign the <code>Headers</code> object to the <code>headers</code> option:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>const myHeaders = new Headers();\nmyHeaders.append(\"Content-Type\", \"application/json\");\n\nconst response = await fetch(\"https://example.org/post\", {\n  method: \"POST\",\n  headers: myHeaders,\n  body: JSON.stringify({ username: \"example\" }),\n  // …\n});\n</code></pre></div>\n<p>Compared to using plain objects, the <code>Headers</code> object provides some additional input sanitization. For example, it normalizes header names to lowercase, strips leading and trailing whitespace from header values, and prevents certain headers from being set. Many headers are set automatically by the browser and can't be set by a script: these are called <a href=\"/en-US/docs/Glossary/Forbidden_request_header\">Forbidden request headers</a>. If the <a href=\"/en-US/docs/Web/API/Request/mode\" title=\"mode\"><code>mode</code></a> option is set to <code>no-cors</code>, then the set of permitted headers is further restricted.</p>"}},{"type":"prose","value":{"id":"sending_data_in_a_get_request","title":"Sending data in a GET request","isH3":true,"content":"<p><code>GET</code> requests don't have a body, but you can still send data to the server by appending it to the URL as a query string. This is a common way to send form data to the server. You can do this by using <a href=\"/en-US/docs/Web/API/URLSearchParams\"><code>URLSearchParams</code></a> to encode the data, and then appending it to the URL:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>const params = new URLSearchParams();\nparams.append(\"username\", \"example\");\n\n// GET request sent to https://example.org/login?username=example\nconst response = await fetch(`https://example.org/login?${params}`);\n</code></pre></div>"}},{"type":"prose","value":{"id":"making_cross-origin_requests","title":"Making cross-origin requests","isH3":true,"content":"<p>Whether a request can be made cross-origin or not is determined by the value of the <a href=\"/en-US/docs/Web/API/RequestInit#mode\"><code>RequestInit.mode</code></a> option. This may take one of three values: <code>cors</code>, <code>same-origin</code>, or <code>no-cors</code>.</p>\n<ul>\n<li>\n<p>For fetch requests the default value of <code>mode</code> is <code>cors</code>, meaning that if the request is cross-origin then it will use the <a href=\"/en-US/docs/Web/HTTP/Guides/CORS\">Cross-Origin Resource Sharing (CORS)</a> mechanism. This means that:</p>\n<ul>\n<li>if the request is a <a href=\"/en-US/docs/Web/HTTP/Guides/CORS#simple_requests\">simple request</a>, then the request will always be sent, but the server must respond with the correct <a href=\"/en-US/docs/Web/HTTP/Reference/Headers/Access-Control-Allow-Origin\"><code>Access-Control-Allow-Origin</code></a> header or the browser will not share the response with the caller.</li>\n<li>if the request is not a simple request, then the browser will send a <a href=\"/en-US/docs/Web/HTTP/Guides/CORS#preflighted_requests\">preflighted request</a> to check that the server understands CORS and allows the request, and the real request will not be sent unless the server responds to the preflighted request with the appropriate CORS headers.</li>\n</ul>\n</li>\n<li>\n<p>Setting <code>mode</code> to <code>same-origin</code> disallows cross-origin requests completely.</p>\n</li>\n<li>\n<p>Setting <code>mode</code> to <code>no-cors</code> disables CORS for cross-origin requests. This restricts the headers that may be set, and restricts methods to GET, HEAD, and POST. The response is <em>opaque</em>, meaning that its headers and body are not available to JavaScript. Most of the time a website should not use <code>no-cors</code>: the main application of it is for certain service worker use cases.</p>\n</li>\n</ul>\n<p>See the reference documentation for <a href=\"/en-US/docs/Web/API/RequestInit#mode\"><code>RequestInit.mode</code></a> for more details.</p>"}},{"type":"prose","value":{"id":"including_credentials","title":"Including credentials","isH3":true,"content":"<p>In the context of the Fetch API, a credential is an extra piece of data sent along with the request that the server may use to authenticate the user. All the following items are considered to be credentials:</p>\n<ul>\n<li>HTTP cookies</li>\n<li><a href=\"/en-US/docs/Glossary/TLS\">TLS</a> client certificates</li>\n<li>The <a href=\"/en-US/docs/Web/HTTP/Reference/Headers/Authorization\"><code>Authorization</code></a> and <a href=\"/en-US/docs/Web/HTTP/Reference/Headers/Proxy-Authorization\"><code>Proxy-Authorization</code></a> headers.</li>\n</ul>\n<p>By default, credentials are only included in same-origin requests. To customize this behavior, as well as to control whether the browser respects any <strong><code>Set-Cookie</code></strong> response headers, set the <a href=\"/en-US/docs/Web/API/RequestInit#credentials\"><code>credentials</code></a> option, which can take one of the following three values:</p>\n<ul>\n<li><code>omit</code>: never send credentials in the request or include credentials in the response.</li>\n<li><code>same-origin</code> (the default): only send and include credentials for same-origin requests.</li>\n<li><code>include</code>: always include credentials, even cross-origin.</li>\n</ul>\n<p>Note that if a cookie's <a href=\"/en-US/docs/Web/HTTP/Reference/Headers/Set-Cookie#samesitesamesite-value\"><code>SameSite</code></a> attribute is set to <code>Strict</code> or <code>Lax</code>, then the cookie will not be sent cross-site, even if <code>credentials</code> is set to <code>include</code>.</p>\n<p>Including credentials in cross-origin requests can make a site vulnerable to <a href=\"/en-US/docs/Glossary/CSRF\">CSRF</a> attacks, so even if <code>credentials</code> is set to <code>include</code>, the server must also agree to their inclusion by including the <a href=\"/en-US/docs/Web/HTTP/Reference/Headers/Access-Control-Allow-Credentials\"><code>Access-Control-Allow-Credentials</code></a> header in its response. Additionally, in this situation the server must explicitly specify the client's origin in the <a href=\"/en-US/docs/Web/HTTP/Reference/Headers/Access-Control-Allow-Origin\"><code>Access-Control-Allow-Origin</code></a> response header (that is, <code>*</code> is not allowed).</p>\n<p>This means that if <code>credentials</code> is set to <code>include</code> and the request is cross-origin, then:</p>\n<ul>\n<li>\n<p>If the request is a <a href=\"/en-US/docs/Web/HTTP/Guides/CORS#simple_requests\">simple request</a>, then the request will be sent with credentials, but the server must set the <a href=\"/en-US/docs/Web/HTTP/Reference/Headers/Access-Control-Allow-Credentials\"><code>Access-Control-Allow-Credentials</code></a> and <a href=\"/en-US/docs/Web/HTTP/Reference/Headers/Access-Control-Allow-Origin\"><code>Access-Control-Allow-Origin</code></a> response headers, or the browser will return a network error to the caller. If the server does set the correct headers, then the response, including credentials, will be delivered to the caller.</p>\n</li>\n<li>\n<p>If the request is not a simple request, then the browser will send a <a href=\"/en-US/docs/Web/HTTP/Guides/CORS#preflighted_requests\">preflighted request</a> without credentials, and the server must set the <a href=\"/en-US/docs/Web/HTTP/Reference/Headers/Access-Control-Allow-Credentials\"><code>Access-Control-Allow-Credentials</code></a> and <a href=\"/en-US/docs/Web/HTTP/Reference/Headers/Access-Control-Allow-Origin\"><code>Access-Control-Allow-Origin</code></a> response headers, or the browser will return a network error to the caller. If the server does set the correct headers, then the browser will follow up with the real request, including credentials, and will deliver the real response, including credentials, to the caller.</p>\n</li>\n</ul>"}},{"type":"prose","value":{"id":"creating_a_request_object","title":"Creating a <code>Request</code> object","isH3":true,"content":"<p>The <a href=\"/en-US/docs/Web/API/Request/Request\" title=\"Request()\"><code>Request()</code></a> constructor takes the same arguments as <code>fetch()</code> itself. This means that instead of passing options into <code>fetch()</code>, you can pass the same options to the <code>Request()</code> constructor, and then pass that object to <code>fetch()</code>.</p>\n<p>For example, we can make a POST request by passing options into <code>fetch()</code> using code like this:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>const myHeaders = new Headers();\nmyHeaders.append(\"Content-Type\", \"application/json\");\n\nconst response = await fetch(\"https://example.org/post\", {\n  method: \"POST\",\n  body: JSON.stringify({ username: \"example\" }),\n  headers: myHeaders,\n});\n</code></pre></div>\n<p>However, we could rewrite this to pass the same arguments to the <code>Request()</code> constructor:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>const myHeaders = new Headers();\nmyHeaders.append(\"Content-Type\", \"application/json\");\n\nconst myRequest = new Request(\"https://example.org/post\", {\n  method: \"POST\",\n  body: JSON.stringify({ username: \"example\" }),\n  headers: myHeaders,\n});\n\nconst response = await fetch(myRequest);\n</code></pre></div>\n<p>This also means that you can create a request from another request, while changing some of its properties using the second argument:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>async function post(request) {\n  try {\n    const response = await fetch(request);\n    const result = await response.json();\n    console.log(\"Success:\", result);\n  } catch (error) {\n    console.error(\"Error:\", error);\n  }\n}\n\nconst request1 = new Request(\"https://example.org/post\", {\n  method: \"POST\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ username: \"example1\" }),\n});\n\nconst request2 = new Request(request1, {\n  body: JSON.stringify({ username: \"example2\" }),\n});\n\npost(request1);\npost(request2);\n</code></pre></div>"}},{"type":"prose","value":{"id":"canceling_a_request","title":"Canceling a request","isH3":false,"content":"<p>To make a request cancelable, create an <a href=\"/en-US/docs/Web/API/AbortController\"><code>AbortController</code></a>, and assign its <a href=\"/en-US/docs/Web/API/AbortSignal\"><code>AbortSignal</code></a> to the request's <code>signal</code> property.</p>\n<p>To cancel the request, call the controller's <a href=\"/en-US/docs/Web/API/AbortController/abort\" title=\"abort()\"><code>abort()</code></a> method. The <code>fetch()</code> call will reject the promise with an <code>AbortError</code> exception.</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>const controller = new AbortController();\n\nconst fetchButton = document.querySelector(\"#fetch\");\nfetchButton.addEventListener(\"click\", async () =&gt; {\n  try {\n    console.log(\"Starting fetch\");\n    const response = await fetch(\"https://example.org/get\", {\n      signal: controller.signal,\n    });\n    console.log(`Response: ${response.status}`);\n  } catch (e) {\n    console.error(`Error: ${e}`);\n  }\n});\n\nconst cancelButton = document.querySelector(\"#cancel\");\ncancelButton.addEventListener(\"click\", () =&gt; {\n  controller.abort();\n  console.log(\"Canceled fetch\");\n});\n</code></pre></div>\n<p>If the request is aborted after the <code>fetch()</code> call has been fulfilled but before the response body has been read, then attempting to read the response body will reject with an <code>AbortError</code> exception.</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>async function get() {\n  const controller = new AbortController();\n  const request = new Request(\"https://example.org/get\", {\n    signal: controller.signal,\n  });\n\n  const response = await fetch(request);\n  controller.abort();\n  // The next line will throw `AbortError`\n  const text = await response.text();\n  console.log(text);\n}\n</code></pre></div>"}},{"type":"prose","value":{"id":"handling_the_response","title":"Handling the response","isH3":false,"content":"<p>As soon as the browser has received the response status and headers from the server (and potentially before the response body itself has been received), the promise returned by <code>fetch()</code> is fulfilled with a <a href=\"/en-US/docs/Web/API/Response\"><code>Response</code></a> object.</p>"}},{"type":"prose","value":{"id":"checking_response_status","title":"Checking response status","isH3":true,"content":"<p>The promise returned by <code>fetch()</code> will reject on some errors, such as a network error or a bad scheme. However, if the server responds with an error like <a href=\"/en-US/docs/Web/HTTP/Reference/Status/404\"><code>404</code></a>, then <code>fetch()</code> fulfills with a <code>Response</code>, so we have to check the status before we can read the response body.</p>\n<p>The <a href=\"/en-US/docs/Web/API/Response/status\"><code>Response.status</code></a> property tells us the numerical status code, and the <a href=\"/en-US/docs/Web/API/Response/ok\"><code>Response.ok</code></a> property returns <code>true</code> if the status is in the <a href=\"/en-US/docs/Web/HTTP/Reference/Status#successful_responses\">200 range</a>.</p>\n<p>A common pattern is to check the value of <code>ok</code> and throw if it is <code>false</code>:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>async function getData() {\n  const url = \"https://example.org/products.json\";\n  try {\n    const response = await fetch(url);\n    if (!response.ok) {\n      throw new Error(`Response status: ${response.status}`);\n    }\n    // …\n  } catch (error) {\n    console.error(error.message);\n  }\n}\n</code></pre></div>"}},{"type":"prose","value":{"id":"checking_the_response_type","title":"Checking the response type","isH3":true,"content":"<p>Responses have a <a href=\"/en-US/docs/Web/API/Response/type\" title=\"type\"><code>type</code></a> property that can be one of the following:</p>\n<ul>\n<li><code>basic</code>: the request was a same-origin request.</li>\n<li><code>cors</code>: the request was a cross-origin CORS request.</li>\n<li><code>opaque</code>: the request was a cross-origin simple request made with the <code>no-cors</code> mode.</li>\n<li><code>opaqueredirect</code>: the request set the <code>redirect</code> option to <code>manual</code>, and the server returned a <a href=\"/en-US/docs/Web/HTTP/Reference/Status#redirection_messages\">redirect status</a>.</li>\n</ul>\n<p>The type determines the possible contents of the response, as follows:</p>\n<ul>\n<li>\n<p>Basic responses exclude response headers from the <a href=\"/en-US/docs/Glossary/Forbidden_response_header_name\">Forbidden response header name</a> list.</p>\n</li>\n<li>\n<p>CORS responses include only response headers from the <a href=\"/en-US/docs/Glossary/CORS-safelisted_response_header\">CORS-safelisted response header</a> list.</p>\n</li>\n<li>\n<p>Opaque responses and opaque redirect responses have a <code>status</code> of <code>0</code>, an empty header list, and a <code>null</code> body.</p>\n</li>\n</ul>"}},{"type":"prose","value":{"id":"checking_headers","title":"Checking headers","isH3":true,"content":"<p>Just like the request, the response has a <a href=\"/en-US/docs/Web/API/Response/headers\" title=\"headers\"><code>headers</code></a> property which is a <a href=\"/en-US/docs/Web/API/Headers\"><code>Headers</code></a> object, and this contains any response headers that are exposed to scripts, subject to the exclusions made based on the response type.</p>\n<p>A common use case for this is to check the content type before trying to read the body:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>async function fetchJSON(request) {\n  try {\n    const response = await fetch(request);\n    const contentType = response.headers.get(\"content-type\");\n    if (!contentType || !contentType.includes(\"application/json\")) {\n      throw new TypeError(\"Oops, we haven't got JSON!\");\n    }\n    // Otherwise, we can read the body as JSON\n  } catch (error) {\n    console.error(\"Error:\", error);\n  }\n}\n</code></pre></div>"}},{"type":"prose","value":{"id":"reading_the_response_body","title":"Reading the response body","isH3":true,"content":"<p>The <code>Response</code> interface provides a number of methods to retrieve the entire body contents in a variety of different formats:</p>\n<ul>\n<li><a href=\"/en-US/docs/Web/API/Response/arrayBuffer\"><code>Response.arrayBuffer()</code></a></li>\n<li><a href=\"/en-US/docs/Web/API/Response/blob\"><code>Response.blob()</code></a></li>\n<li><a href=\"/en-US/docs/Web/API/Response/formData\"><code>Response.formData()</code></a></li>\n<li><a href=\"/en-US/docs/Web/API/Response/json\"><code>Response.json()</code></a></li>\n<li><a href=\"/en-US/docs/Web/API/Response/text\"><code>Response.text()</code></a></li>\n</ul>\n<p>These are all asynchronous methods, returning a <a href=\"/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\"><code>Promise</code></a> which will be fulfilled with the body content.</p>\n<p>In this example, we fetch an image and read it as a <a href=\"/en-US/docs/Web/API/Blob\"><code>Blob</code></a>, which we can then use to create an object URL:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>const image = document.querySelector(\"img\");\n\nconst url = \"flowers.jpg\";\n\nasync function setImage() {\n  try {\n    const response = await fetch(url);\n    if (!response.ok) {\n      throw new Error(`Response status: ${response.status}`);\n    }\n    const blob = await response.blob();\n    const objectURL = URL.createObjectURL(blob);\n    image.src = objectURL;\n  } catch (e) {\n    console.error(e);\n  }\n}\n</code></pre></div>\n<p>The method will throw an exception if the response body is not in the appropriate format: for example, if you call <code>json()</code> on a response that can't be parsed as JSON.</p>"}},{"type":"prose","value":{"id":"streaming_the_response_body","title":"Streaming the response body","isH3":true,"content":"<p>Request and response bodies are actually <a href=\"/en-US/docs/Web/API/ReadableStream\"><code>ReadableStream</code></a> objects, and whenever you read them, you're streaming the content. This is good for memory efficiency, because the browser doesn't have to buffer the entire response in memory before the caller retrieves it using a method like <code>json()</code>.</p>\n<p>This also means that the caller can process the content incrementally as it is received.</p>\n<p>For example, consider a <code>GET</code> request that fetches a large text file and processes it in some way, or displays it to the user:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>const url = \"https://www.example.org/a-large-file.txt\";\n\nasync function fetchText(url) {\n  try {\n    const response = await fetch(url);\n    if (!response.ok) {\n      throw new Error(`Response status: ${response.status}`);\n    }\n\n    const text = await response.text();\n    console.log(text);\n  } catch (e) {\n    console.error(e);\n  }\n}\n</code></pre></div>\n<p>If we use <a href=\"/en-US/docs/Web/API/Response/text\"><code>Response.text()</code></a>, as above, we must wait until the whole file has been received before we can process any of it.</p>\n<p>If we stream the response instead, we can process chunks of the body as they are received from the network:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>const url = \"https://www.example.org/a-large-file.txt\";\n\nasync function fetchTextAsStream(url) {\n  try {\n    const response = await fetch(url);\n    if (!response.ok) {\n      throw new Error(`Response status: ${response.status}`);\n    }\n\n    const stream = response.body.pipeThrough(new TextDecoderStream());\n    for await (const value of stream) {\n      console.log(value);\n    }\n  } catch (e) {\n    console.error(e);\n  }\n}\n</code></pre></div>\n<p>In this example, we <a href=\"/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of\">iterate asynchronously</a> over the stream, processing each chunk as it arrives.</p>\n<p>Note that when you access the body directly like this, you get the raw bytes of the response and must transform it yourself. In this case we call <a href=\"/en-US/docs/Web/API/ReadableStream/pipeThrough\"><code>ReadableStream.pipeThrough()</code></a> to pipe the response through a <a href=\"/en-US/docs/Web/API/TextDecoderStream\"><code>TextDecoderStream</code></a>, which decodes the UTF-8-encoded body data as text.</p>"}},{"type":"prose","value":{"id":"processing_a_text_file_line_by_line","title":"Processing a text file line by line","isH3":true,"content":"<p>In the example below, we fetch a text resource and process it line by line, using a regular expression to look for line endings. For simplicity, we assume the text is UTF-8, and don't handle fetch errors:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>async function* makeTextFileLineIterator(fileURL) {\n  const response = await fetch(fileURL);\n  const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();\n\n  let { value: chunk = \"\", done: readerDone } = await reader.read();\n\n  const newline = /\\r?\\n/g;\n  let startIndex = 0;\n\n  while (true) {\n    const result = newline.exec(chunk);\n    if (!result) {\n      if (readerDone) break;\n      const remainder = chunk.slice(startIndex);\n      ({ value: chunk, done: readerDone } = await reader.read());\n      chunk = remainder + (chunk || \"\");\n      startIndex = newline.lastIndex = 0;\n      continue;\n    }\n    yield chunk.substring(startIndex, result.index);\n    startIndex = newline.lastIndex;\n  }\n\n  if (startIndex &lt; chunk.length) {\n    // Last line didn't end in a newline char\n    yield chunk.substring(startIndex);\n  }\n}\n\nasync function run(urlOfFile) {\n  for await (const line of makeTextFileLineIterator(urlOfFile)) {\n    processLine(line);\n  }\n}\n\nfunction processLine(line) {\n  console.log(line);\n}\n\nrun(\"https://www.example.org/a-large-file.txt\");\n</code></pre></div>"}},{"type":"prose","value":{"id":"locked_and_disturbed_streams","title":"Locked and disturbed streams","isH3":true,"content":"<p>The consequences of request and response bodies being streams are that:</p>\n<ul>\n<li>if a reader has been attached to a stream using <code>ReadableStream.getReader()</code>, then the stream is <em>locked</em>, and nothing else can read the stream.</li>\n<li>if any content has been read from the stream, then the stream is <em>disturbed</em>, and nothing else can read from the stream.</li>\n</ul>\n<p>This means it's not possible to read the same response (or request) body more than once:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js example-bad notranslate\"><code>async function getData() {\n  const url = \"https://example.org/products.json\";\n  try {\n    const response = await fetch(url);\n    if (!response.ok) {\n      throw new Error(`Response status: ${response.status}`);\n    }\n\n    const result1 = await response.json();\n    const result2 = await response.json(); // will throw\n  } catch (error) {\n    console.error(error.message);\n  }\n}\n</code></pre></div>\n<p>If you do need to read the body more than once, you must call <a href=\"/en-US/docs/Web/API/Response/clone\"><code>Response.clone()</code></a> before reading the body:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>async function getData() {\n  const url = \"https://example.org/products.json\";\n  try {\n    const response1 = await fetch(url);\n    if (!response1.ok) {\n      throw new Error(`Response status: ${response1.status}`);\n    }\n\n    const response2 = response1.clone();\n\n    const result1 = await response1.json();\n    const result2 = await response2.json();\n  } catch (error) {\n    console.error(error.message);\n  }\n}\n</code></pre></div>\n<p>This is a common pattern when <a href=\"/en-US/docs/Web/Progressive_web_apps/Guides/Caching\">implementing an offline cache with service workers</a>. The service worker wants to return the response to the app, but also to cache the response. So it clones the response, returns the original, and caches the clone:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>async function cacheFirst(request) {\n  const cachedResponse = await caches.match(request);\n  if (cachedResponse) {\n    return cachedResponse;\n  }\n  try {\n    const networkResponse = await fetch(request);\n    if (networkResponse.ok) {\n      const cache = await caches.open(\"MyCache_1\");\n      cache.put(request, networkResponse.clone());\n    }\n    return networkResponse;\n  } catch (error) {\n    return Response.error();\n  }\n}\n\nself.addEventListener(\"fetch\", (event) =&gt; {\n  if (precachedResources.includes(url.pathname)) {\n    event.respondWith(cacheFirst(event.request));\n  }\n});\n</code></pre></div>"}},{"type":"prose","value":{"id":"see_also","title":"See also","isH3":false,"content":"<ul>\n<li><a href=\"/en-US/docs/Web/API/Service_Worker_API\">Service Worker API</a></li>\n<li><a href=\"/en-US/docs/Web/API/Streams_API\">Streams API</a></li>\n<li><a href=\"/en-US/docs/Web/HTTP/Guides/CORS\">CORS</a></li>\n<li><a href=\"/en-US/docs/Web/HTTP\">HTTP</a></li>\n<li><a href=\"https://github.com/mdn/dom-examples/tree/main/fetch\" class=\"external\" target=\"_blank\">Fetch examples on GitHub</a></li>\n</ul>"}}],"isActive":true,"isMarkdown":true,"isTranslated":false,"locale":"en-US","mdn_url":"/en-US/docs/Web/API/Fetch_API/Using_Fetch","modified":"2025-08-20T18:33:20.000Z","native":"English (US)","noIndexing":false,"other_translations":[{"locale":"en-US","title":"Using the Fetch API","native":"English (US)"},{"locale":"de","title":"Verwenden der Fetch API","native":"Deutsch"},{"locale":"es","title":"Uso de Fetch","native":"Español"},{"locale":"fr","title":"Utiliser l'API Fetch","native":"Français"},{"locale":"ja","title":"フェッチ API の使用","native":"日本語"},{"locale":"ko","title":"Fetch API 사용하기","native":"한국어"},{"locale":"pt-BR","title":"Usando Fetch","native":"Português (do Brasil)"},{"locale":"ru","title":"Использование Fetch","native":"Русский"},{"locale":"zh-CN","title":"使用 Fetch","native":"中文 (简体)"},{"locale":"zh-TW","title":"Using Fetch","native":"正體中文 (繁體)"}],"pageTitle":"Using the Fetch API - Web APIs | MDN","parents":[{"uri":"/en-US/docs/Web","title":"Web"},{"uri":"/en-US/docs/Web/API","title":"Web APIs"},{"uri":"/en-US/docs/Web/API/Fetch_API","title":"Fetch API"},{"uri":"/en-US/docs/Web/API/Fetch_API/Using_Fetch","title":"Using the Fetch API"}],"popularity":0.3632298834433366,"short_title":"Using the Fetch API","sidebarHTML":"<ol><li class=\"section\"><a href=\"/en-US/docs/Web/API/Fetch_API\">Fetch API</a></li><li><details open=\"\"><summary><span>Guides</span></summary><ol><li><em><a href=\"/en-US/docs/Web/API/Fetch_API/Using_Fetch\" aria-current=\"page\">Using the Fetch API</a></em></li><li><a href=\"/en-US/docs/Web/API/Fetch_API/Using_Deferred_Fetch\">Using Deferred Fetch</a></li></ol></details></li><li><details open=\"\"><summary><span>Interfaces</span></summary><ol><li><a href=\"/en-US/docs/Web/API/DeferredRequestInit\"><code>DeferredRequestInit</code></a><abbr class=\"icon icon-experimental\" title=\"Experimental. Expect behavior to change in the future.\">\n<span class=\"visually-hidden\">Experimental</span>\n</abbr></li><li><a href=\"/en-US/docs/Web/API/FetchLaterResult\"><code>FetchLaterResult</code></a><abbr class=\"icon icon-experimental\" title=\"Experimental. Expect behavior to change in the future.\">\n<span class=\"visually-hidden\">Experimental</span>\n</abbr></li><li><a href=\"/en-US/docs/Web/API/Headers\"><code>Headers</code></a></li><li><a href=\"/en-US/docs/Web/API/Request\"><code>Request</code></a></li><li><a href=\"/en-US/docs/Web/API/RequestInit\"><code>RequestInit</code></a></li><li><a href=\"/en-US/docs/Web/API/Response\"><code>Response</code></a></li></ol></details></li><li><details open=\"\"><summary><span>Methods</span></summary><ol><li><a href=\"/en-US/docs/Web/API/Window/fetch\"><code>Window<wbr>.fetch()</code></a></li><li><a href=\"/en-US/docs/Web/API/WorkerGlobalScope/fetch\"><code>WorkerGlobalScope<wbr>.fetch()</code></a></li><li><a href=\"/en-US/docs/Web/API/Window/fetchLater\"><code>Window<wbr>.fetchLater()</code></a><abbr class=\"icon icon-experimental\" title=\"Experimental. Expect behavior to change in the future.\">\n<span class=\"visually-hidden\">Experimental</span>\n</abbr></li></ol></details></li></ol>","source":{"folder":"en-us/web/api/fetch_api/using_fetch","github_url":"https://github.com/mdn/content/blob/main/files/en-us/web/api/fetch_api/using_fetch/index.md","last_commit_url":"https://github.com/mdn/content/commit/fe1d7fb9b67ce826c4a748ce00e7b35ac4a54c7f","filename":"index.md"},"summary":"The Fetch API provides a JavaScript interface for making HTTP requests and processing the responses.","title":"Using the Fetch API","titleHTML":"Using the Fetch API","toc":[{"text":"Making a request","id":"making_a_request"},{"text":"Canceling a request","id":"canceling_a_request"},{"text":"Handling the response","id":"handling_the_response"},{"text":"See also","id":"see_also"}],"pageType":"guide"},"url":"/en-US/docs/Web/API/Fetch_API/Using_Fetch","renderer":"Doc"}