Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

whatwg-fetch

github57.6mMIT3.6.20TypeScript support: definitely-typed

A window.fetch polyfill.

readme

window.fetch polyfill

OpenSSF Scorecard

The fetch() function is a Promise-based mechanism for programmatically making web requests in the browser. This project is a polyfill that implements a subset of the standard Fetch specification, enough to make fetch a viable replacement for most uses of XMLHttpRequest in traditional web applications.

Table of Contents

Read this first

  • If you believe you found a bug with how fetch behaves in your browser, please don't open an issue in this repository unless you are testing in an old version of a browser that doesn't support window.fetch natively. Make sure you read this entire readme, especially the Caveats section, as there's probably a known work-around for an issue you've found. This project is a polyfill, and since all modern browsers now implement the fetch function natively, no code from this project actually takes any effect there. See Browser support for detailed information.

  • If you have trouble making a request to another domain (a different subdomain or port number also constitutes another domain), please familiarize yourself with all the intricacies and limitations of CORS requests. Because CORS requires participation of the server by implementing specific HTTP response headers, it is often nontrivial to set up or debug. CORS is exclusively handled by the browser's internal mechanisms which this polyfill cannot influence.

  • This project doesn't work under Node.js environments. It's meant for web browsers only. You should ensure that your application doesn't try to package and run this on the server.

  • If you have an idea for a new feature of fetch, submit your feature requests to the specification's repository. We only add features and APIs that are part of the Fetch specification.

Installation

npm install whatwg-fetch --save

You will also need a Promise polyfill for older browsers. We recommend taylorhakes/promise-polyfill for its small size and Promises/A+ compatibility.

Usage

Importing

Importing will automatically polyfill window.fetch and related APIs:

import 'whatwg-fetch'

window.fetch(...)

If for some reason you need to access the polyfill implementation, it is available via exports:

import {fetch as fetchPolyfill} from 'whatwg-fetch'

window.fetch(...)   // use native browser version
fetchPolyfill(...)  // use polyfill implementation

This approach can be used to, for example, use abort functionality in browsers that implement a native but outdated version of fetch that doesn't support aborting.

For use with webpack, add this package in the entry configuration option before your application entry point:

entry: ['whatwg-fetch', ...]

HTML

fetch('/users.html')
  .then(function(response) {
    return response.text()
  }).then(function(body) {
    document.body.innerHTML = body
  })

JSON

fetch('/users.json')
  .then(function(response) {
    return response.json()
  }).then(function(json) {
    console.log('parsed json', json)
  }).catch(function(ex) {
    console.log('parsing failed', ex)
  })

Response metadata

fetch('/users.json').then(function(response) {
  console.log(response.headers.get('Content-Type'))
  console.log(response.headers.get('Date'))
  console.log(response.status)
  console.log(response.statusText)
})

Post form

var form = document.querySelector('form')

fetch('/users', {
  method: 'POST',
  body: new FormData(form)
})

Post JSON

fetch('/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'Hubot',
    login: 'hubot',
  })
})

File upload

var input = document.querySelector('input[type="file"]')

var data = new FormData()
data.append('file', input.files[0])
data.append('user', 'hubot')

fetch('/avatars', {
  method: 'POST',
  body: data
})

Caveats

  • The Promise returned from fetch() won't reject on HTTP error status even if the response is an HTTP 404 or 500. Instead, it will resolve normally, and it will only reject on network failure or if anything prevented the request from completing.

  • For maximum browser compatibility when it comes to sending & receiving cookies, always supply the credentials: 'same-origin' option instead of relying on the default. See Sending cookies.

  • Not all Fetch standard options are supported in this polyfill. For instance, redirect and cache directives are ignored.

  • keepalive is not supported because it would involve making a synchronous XHR, which is something this project is not willing to do. See issue #700 for more information.

Handling HTTP error statuses

To have fetch Promise reject on HTTP error statuses, i.e. on any non-2xx status, define a custom response handler:

function checkStatus(response) {
  if (response.status >= 200 && response.status < 300) {
    return response
  } else {
    var error = new Error(response.statusText)
    error.response = response
    throw error
  }
}

function parseJSON(response) {
  return response.json()
}

fetch('/users')
  .then(checkStatus)
  .then(parseJSON)
  .then(function(data) {
    console.log('request succeeded with JSON response', data)
  }).catch(function(error) {
    console.log('request failed', error)
  })

Sending cookies

For CORS requests, use credentials: 'include' to allow sending credentials to other domains:

fetch('https://example.com:1234/users', {
  credentials: 'include'
})

The default value for credentials is "same-origin".

The default for credentials wasn't always the same, though. The following versions of browsers implemented an older version of the fetch specification where the default was "omit":

  • Firefox 39-60
  • Chrome 42-67
  • Safari 10.1-11.1.2

If you target these browsers, it's advisable to always specify credentials: 'same-origin' explicitly with all fetch requests instead of relying on the default:

fetch('/users', {
  credentials: 'same-origin'
})

Note: due to limitations of XMLHttpRequest, using credentials: 'omit' is not respected for same domains in browsers where this polyfill is active. Cookies will always be sent to same domains in older browsers.

Receiving cookies

As with XMLHttpRequest, the Set-Cookie response header returned from the server is a forbidden header name and therefore can't be programmatically read with response.headers.get(). Instead, it's the browser's responsibility to handle new cookies being set (if applicable to the current URL). Unless they are HTTP-only, new cookies will be available through document.cookie.

Redirect modes

The Fetch specification defines these values for the redirect option: "follow" (the default), "error", and "manual".

Due to limitations of XMLHttpRequest, only the "follow" mode is available in browsers where this polyfill is active.

Obtaining the Response URL

Due to limitations of XMLHttpRequest, the response.url value might not be reliable after HTTP redirects on older browsers.

The solution is to configure the server to set the response HTTP header X-Request-URL to the current URL after any redirect that might have happened. It should be safe to set it unconditionally.

# Ruby on Rails controller example
response.headers['X-Request-URL'] = request.url

This server workaround is necessary if you need reliable response.url in Firefox < 32, Chrome < 37, Safari, or IE.

Aborting requests

This polyfill supports the abortable fetch API. However, aborting a fetch requires use of two additional DOM APIs: AbortController and AbortSignal. Typically, browsers that do not support fetch will also not support AbortController or AbortSignal. Consequently, you will need to include an additional polyfill for these APIs to abort fetches:

import 'yet-another-abortcontroller-polyfill'
import {fetch} from 'whatwg-fetch'

// use native browser implementation if it supports aborting
const abortableFetch = ('signal' in new Request('')) ? window.fetch : fetch

const controller = new AbortController()

abortableFetch('/avatars', {
  signal: controller.signal
}).catch(function(ex) {
  if (ex.name === 'AbortError') {
    console.log('request aborted')
  }
})

// some time later...
controller.abort()

Browser Support

  • Chrome
  • Firefox
  • Safari 6.1+
  • Internet Explorer 10+

Note: modern browsers such as Chrome, Firefox, Microsoft Edge, and Safari contain native implementations of window.fetch, therefore the code from this polyfill doesn't have any effect on those browsers. If you believe you've encountered an error with how window.fetch is implemented in any of these browsers, you should file an issue with that browser vendor instead of this project.

changelog

Changelog

All notable changes to this project will be documented in this file. Dates are displayed in UTC.

3.6.20 (2023-12-13)

Bug Fixes

3.6.19 (2023-09-11)

Bug Fixes

  • Have unique error messages for xhr timeouts and errors (#1380) (7170f0b)

v3.6.18

  • Fix - File fetching broken since commit 0c1d2b9 #1375
  • Remove broken links 1dc07c6
  • automatically generate a changelog 0e7d1dd

v3.6.17

20 July 2023

v3.6.16

18 July 2023

v3.6.15

18 July 2023

v3.6.14

18 July 2023

v3.6.13

18 July 2023

  • respect charset within readBlobAsText #1059

v3.6.12

18 July 2023

  • fix: Headers only accepts array which have nested array of length 2 #1235

v3.6.11

18 July 2023

  • Define Body.arrayBuffer even if support.blob is false #992

v3.6.10

18 July 2023

  • use globals if they exist dffc542

v3.6.9

18 July 2023

  • fix: when no body supplied, do not set bodyUsed to true 7d92dff

v3.6.8

18 July 2023

  • validate status is in range #1213

v3.6.7

18 July 2023

v3.6.6

18 July 2023

  • fix: ignore not throw on invalid response headers #930

v3.6.5

18 July 2023

  • Add some missed methods which should be normalized as uppercase a43b628
  • Update caniuse link to use HTTPS and new pattern fb5b0cf

v3.6.4

18 July 2023

  • always set a signal on Request d1d09fb

v3.6.3

18 July 2023

  • Compatible global equals to the false 7727e50

v3.6.2

27 February 2021

  • Revert "Represent non-stringified JSON request body as an [object Object] string" e42f201

v3.6.1

18 February 2021

v3.6.0

18 February 2021

  • Fix statusText: undefined should give '' and null should give 'null' b5c8bd0
  • Represent non-stringified JSON request body as an [object Object] string 5c6b055
  • Fix eslint and eslint-plugin-github dependency conflicts 190e698

v3.5.0

6 November 2020

v3.4.1

7 September 2020

  • Add npmignore file to ensure we always publish the dist directory 7ca02eb
  • Make the clean task remove the dist directory and the default task create it fd23745

v3.4.0

7 August 2020

  • Use globalThis as the global object if it exists 96c2651

v3.3.1

4 August 2020

  • rename variable to no longer shadow over function of same name c5db762
  • remove semicolon to pass linting f264aa5

v3.3.0

4 August 2020

  • Make Response.arrayBuffer() always resolve with a ArrayBuffer #801
  • Stop using top-level this to stop rollup warning #802
  • Recommend an AbortController polyfill which is fully synchronous #800
  • Add keepalive caveat #780
  • Throw a TypeError if Request or Response functions are called without new 5ef028d
  • If headers are passed in via a Record then do not normalise the header names as part of the request b65ed60
  • Update fetch.js 37b55c2

v3.2.0

9 July 2020

  • Detect if DOMException exists via typeof instead of trying to call it and catching the exception which may get thrown #724
  • use this if self is not defined #657
  • create variable called global which is either self or this a0783a5
  • Add support for no-cache and no-store via a cache-busting querystring parameter a0dcd85
  • make global this correct when using rollup 6e9fc0e

v3.1.1

8 July 2020

  • check if Content-Type header exists prior to examining the value #792
  • Move from Travis to GitHub Actions #793

v3.1.0

29 June 2020

v3.0.1

8 July 2020

  • check if Content-Type header exists prior to examining the value #792
  • Move from Travis to GitHub Actions #793
  • Co-authored-by: Jake Champion <me@jakechampion.name> #575
  • work around IE XHR bug with '' URL Fixes #618 #619
  • Allow exclamation mark as valid header character #745
  • Avoid blob conversion for specific requests #752
  • Compatibility for fetch-mock using proxy-pollyfill #736
  • Change default statusText for Response #698
  • Document more common pitfalls in the README #734
  • field name can not by empty #684
  • work around IE XHR bug with '' URL Fixes #618 (#619) #618
  • Clarify what parts of the standard we don't want to implement #661
  • Document more caveats 9a0bce2
  • Fix issue #533 7f030fa
  • Compatibility with newer eslint-plugin-github 1821b74

v3.0.0

7 September 2018

  • Add flow definitions #654
  • Match spec behavior re: unsupported body type #651
  • Update Karma and detect available browsers when testing #652
  • Adopt Contributor Covenant Code of Conduct #649
  • Change credentials default value to same-origin #640
  • Switch test suite from PhantomJS to Karma #626
  • Support abort API #592
  • build/distribute as UMD #616
  • Test signal reuse. Add AbortSignal polyfill. #2
  • Clear abort event listener for all xhr completion states. #1
  • Expand install & importing documentation #569
  • Match spec behavior re: unsupported body type #576
  • Run test files through prettier 0a57487
  • Unwrap fetch.js to be a clean module file 8aec47c
  • Switch from PhantomJS to Karma + Chrome/Firefox for testing b539589

v2.0.4

29 March 2018

  • Create CONTRIBUTING.md #604
  • Tweak the wording of the “Read this first” section #553
  • Allow undefined Response status #534
  • Ensure cookies aren't sent if credentials: omit #526
  • Added yarn command as option to installation #492
  • Add global replace for processing raw headers #496
  • Added safari to native fetch browser support. #469
  • Support obs-fold as header delimiter #491
  • Tweak the wording of "Read this first" 54dc3f8
  • Add test for undefined Response status 0ecdd40
  • Fix cookie test with newer versions of Node 7831671

v2.0.3

2 March 2017

  • Accept array in Headers constructor #485
  • Improve README language #483
  • Fix grammar mistake in README #468
  • Remove bower version from release instructions 5cc72dd
  • Remove extra punctuation eebaa2a
  • Fetch 2.0.3 d4ed806

v2.0.2

19 January 2017

  • Treat any non-Request arg to new Request() as string url #465
  • Support Tolerance Provision when parsing headers #449
  • Add test for cloning GET request #440
  • Detect broken URL support in PhantomJS and skip test b285e61
  • Remove secrets 9240ef4
  • fetch 2.0.2 b337f95

v2.0.1

17 November 2016

  • Fix misspelling of [ae]ffect #432
  • Fix reading ArrayBuffer into string on older browsers 6f8529e
  • Only define arrayBuffer() if Blob is also supported 3d3bb0c
  • Display uncaught errors on the test results page 54ec096

v2.0.0

14 November 2016

  • Change Headers multiple value handling for spec compatibility #429
  • Firefox now implements Headers.forEach natively 468f877
  • fetch 2.0.0 c576d61

v1.1.1

17 November 2016

  • Fix reading ArrayBuffer into string on older browsers 1ddcadb
  • Only define arrayBuffer() if Blob is also supported c2556f3
  • fetch 1.1.1 f7a5148

v1.1.0

14 November 2016

  • Support ArrayBufferView types as POST body #430
  • Spec compatibility for Request/Response constructors and cloning #428
  • Improve Readme #427
  • Fix grammar #408
  • Fixed typo in README.md #403
  • make X-Request-URL header case-insensitive #384
  • Better error handling with Saucelabs #354
  • Update Webpack section in README #331
  • Attach FileReader event handlers before calling its read* method #353
  • Default Response status is 200 OK #376
  • Support ArrayBuffer in BodyInit #350
  • Avoid consuming body when cloning #308 #335
  • Rework parsing of raw response HTTP headers #422
  • Allow reusing the same GET Request instance multiple times #411
  • Always construct a new Headers instance in Response #416
  • Rework the Installation section #415
  • More information about cookies #393
  • It looks like Safari 10 didn't ship with native fetch #401
  • Reorganize tests with the new "fetch method" suite ba7ffda
  • Share identical tests between Request & Response 9a04a06
  • ArrayBuffer can now be consumed through blob()/text() 9a703ba

v1.0.0

28 April 2016

  • refactor Header iterator methods #317
  • Add ES2015+ example #287
  • Switch to mocha-phantomjs-core and system PhantomJS #314
  • Reject promise on request timeout #306
  • Use uppercase methods in README #272
  • Guard against xhr.getAllResponseHeaders() being null #289
  • Add support for URLSearchParams POST body #304
  • Add Headers iterators #295
  • fix example #282
  • Drop IE-specific status codes workarounds and require IE10+ #270
  • Reject promise on request timeout #294
  • Make Headers iterable if Symbol is available a1b7674
  • Support URLSearchParams POST body d77810a
  • Fix formatting edb7c73

v0.11.1

5 May 2016

  • Reject promise on request timeout #294
  • Fix formatting 3fc66ed
  • Fetch 0.11.1 7d9a11d
  • Guard against xhr.getAllResponseHeaders() being null 8deb829

v0.11.0

19 January 2016

  • Handle cases where self isn't defined #253
  • Exercise both polyfill and native fetch in test suite #258
  • Make fetch add a Content-Type header based on the type of the body. 1e4a615
  • Cleanup in determining implicit content-type 3b5dc9c
  • Render main test suite as root resource of test server b043384

v0.10.1

2 November 2015

  • Allow making a POST request with an ArrayBuffer body #227
  • Run Sauce Labs CI for pull requests #220
  • Streamline Sauce Labs API interactions 07dc8ae
  • Download and start Sauce Connect manually b3885b4
  • Switch to my credentials for npm publish from CI e0a4851

v0.10.0

12 October 2015

  • Remove moot version property from bower.json #159
  • Use absolute URL in Response.redirect test #219
  • Support Response.error() and Response.redirect() #212
  • Reject the Promise returned by fetch() when Request ctor throws #217
  • Fix incorrect assertion #216
  • Remove superfluous assignment #213
  • Add webpack usage link. #195
  • Allow passing a Request instance to Request constructor #179
  • Properly convert undefined/null header values to strings. #156
  • Code of Conduct #174
  • Improve documentation for fetch caveats #164
  • Opt into new Travis infrastructure #158
  • Merge branch 'orphan-black' #209 #185
  • Add include credentials example. #205
  • Add Request.clone() and Response.clone() methods 46705f7
  • Fix and simplify Request.clone() fd362dd
  • Expand caveats with notes about cookies 184b647

v0.9.0

29 May 2015

  • Implement Headers#forEach correctly #150
  • Test forEach. 2f442ce
  • Fix forEach parameters. 0449483
  • Accept a thisArg forEach parameter. bd2fe03

v0.8.2

19 May 2015

  • Set xhr.withCredentials after xhr.open called. a847967
  • Only support standard options. cc9f4b0
  • Fetch 0.8.2 0b3e1d7

v0.8.1

4 May 2015

v0.8.0

4 May 2015

  • only define _initBody once #136
  • remove un-needed promise allocations in example #120
  • Headers constructor in Response constructor #107
  • Sauce: IE9 #102
  • Sauce Labs: IE 11 #101
  • Sauce Labs #99
  • Add a convenience ok getter on Response #82
  • Follow spec on Headers to throw TypeError, add tests for Headers #85
  • adds .npmignore #84
  • node.js module link #81
  • Add script runner for saucelabs 47fc7d5
  • Split app and server 29cc5dc
  • More scripty ba1214a

v0.7.0

24 January 2015

  • Centralise the checks for blob and form data support #78
  • If cors, with credentials #77
  • Add metadata for repository, bugs and license #67
  • Declare deliberate "async=true" on XMLHttpRequest open #74
  • Fix typo in npm install instructions #71
  • Improve Request/Response BodyInit consuming #70
  • Fix up body consuming on request fbfa9e3
  • Throw TypeError if body is given for GET or HEAD 5ce5677
  • A few more tests and typo fix. 614b2aa

v0.6.1

15 January 2015

  • Add charset content-type tests 7474e42
  • Add additional body init and consume test coverage 9d58648
  • Fix X-Request-URL on CORS requests 4525329

v0.6.0

12 January 2015

  • Suspect this api key was wrong #63
  • Use responseText on IE9 which lacks XHR2 support eeb53d3
  • Tidy up binary file reader 7436589
  • Use xhr.responseType = 'blob' to preserve binary data. 080358d

v0.5.0

12 January 2015

  • Enable travis to publish to npm. #57
  • Make Headers case insensitive though lowercasing. #62
  • Support credentials #56
  • Switch to Mocha #59
  • Test Atomic HTTP redirect handling #55
  • Mark FormData support as optional #54
  • Add promise test helper #53
  • Test in web worker #51
  • Group tests ecd8600
  • Switch to mocha cbd6c66
  • Skip tests in phantomjs 8a4b620

v0.4.0

29 December 2014

  • Assign to self #52
  • Web Workers support #48
  • Align used flag error message to Chrome's implementation #44
  • Add missing quote. #40
  • Align bodyUsed error message to Chrome's implementation e414284
  • Avoid testing implementation specific error messages cc42153
  • Set esnext option 3ebc441

v0.3.2

24 November 2014

  • FormData should only able to consume once #38
  • Test formData body consumption. 4a7e655
  • Fetch 0.3.2 830231e

v0.3.1

21 November 2014

  • Reject promise with TypeError for network failures. #36
  • Reject example promise with an Error. #35
  • Fetch 0.3.1 eb3f9b2

v0.3.0

13 November 2014

  • IE 9+ fixes #28
  • Move body to _body to prevent direct access #32
  • Remove form encoded object body. #30
  • Document how to use in Browserify… #29
  • Auto-detect available port when running headless tests #27
  • Shell highlight #24
  • use shorthand npm installation #23
  • Add name/version/main so it can be installed from npm. #22
  • Add example of success and error handlers #18
  • Test Server #13
  • Travis #12
  • Add test server 3316bda
  • Uppercase the HTTP method name c71f1dd
  • Skip blob tests on phantom c02cad2

v0.2.1

15 October 2014

  • Use of Promise.reject as a constructor #10
  • Fixed uncaught error when a body was consumed more than once. e428559
  • Fetch 0.2.1 8160180

v0.2.0

15 October 2014

  • Parse form encoded response body #8
  • Allow body to be consumed only once #7
  • throw proper errors #5
  • Allow body to be consumed a single time. c7a27dc
  • Parse form encoded response body. 60271ce
  • Extract consumed function. a709976

v0.1.0

13 October 2014