You usually do not need a fetch polyfill to test fetch requests in Cypress. The old experimentalFetchPolyfill setting has been removed; use cy.intercept() to observe or stub requests. Add a polyfill only when the application must support a browser that lacks window.fetch, and load it in the application runtime before code that calls fetch.
Choose the right tool: polyfill or cy.intercept()
These solve different problems. A polyfill supplies a browser API to application code; cy.intercept() lets a Cypress test observe or control HTTP traffic. Cypress’s migration guidance says to remove experimentalFetchPolyfill and use cy.intercept() for fetch requests: Cypress migration guide.
| Need | Use | Runs in |
|---|---|---|
Make fetch available in a browser environment that does not provide it |
A project-appropriate fetch polyfill | The application’s runtime, before application code calls fetch |
| Return predictable API data, inspect a request, or test failure responses | cy.intercept() |
Cypress test setup |
If all supported browsers already provide native fetch, adding a test-only polyfill is unnecessary and may conceal a compatibility problem in the real application.
Stub a fetch-backed request with cy.intercept()
Register the route before visiting the application or performing the action that triggers the request. This complete spec stubs GET /api/users, clicks a control, and checks the response status:
Free tools Windows power users keep installed
One-click scans. No signup required.
#1 Best Overall
describe('user loading', () => {
it('loads users from a stubbed response', () => {
cy.intercept('GET', '/api/users', {
statusCode: 200,
body: [{ id: 1, name: 'Ada' }],
}).as('getUsers')
cy.visit('/')
cy.get('[data-cy=load-users]').click()
cy.wait('@getUsers')
.its('response.statusCode')
.should('eq', 200)
})
})
The test assumes the application has a [data-cy=load-users] control and issues a matching request. Adjust the selector, method, and URL pattern to match your app. Cypress’s recipe index labels this pattern “Stubbing window.fetch”: Cypress recipes.
Serve a fixture instead of inline data
For reusable or larger responses, keep the response in a fixture file and pass its name to the intercept route:
Rank #2
cy.intercept('GET', '/api/users', { fixture: 'users.json' }).as('getUsers')
cy.visit('/')
cy.get('[data-cy=load-users]').click()
cy.wait('@getUsers').its('response.statusCode').should('eq', 200)
Cypress serves fixture data through cy.intercept(), so the test does not need a live API response. See the Cypress fixture documentation.
Scope routes to the test lifecycle
Cypress clears intercepts before each test. Declare a route inside the test or in a beforeEach hook when each test needs it. Shared setup can live in a Cypress support file, which is loaded before each spec; keep that file’s imports lean because the support bundle is loaded for every spec. See Cypress support-file guidance.
Rank #3
If the application really needs a fetch polyfill
- Check the supported browser matrix. Confirm that an environment your application supports lacks native
fetch. A polyfill should address that runtime requirement, not simply the fact that a test uses Cypress. - Add it through the application’s dependency and build process. Load the chosen package before any module that calls
fetch, so the application starts with the API available. - Choose the package and import syntax for your project. These depend on the app’s browser targets and bundler; Cypress does not prescribe a universal third-party package or import recipe.
- Keep request control in the test. Use
cy.intercept()to stub or observe HTTP traffic whether the application calls native or polyfilledfetch.
Do not assume an import in Cypress’s support file installs a polyfill into the application under test (AUT). Cypress documents support-file loading, but the guidance reviewed does not provide a universal method for injecting a third-party polyfill into the AUT window. If your project applies a test-only polyfill in a preload hook, verify that it modifies the AUT’s window and runs before application startup and the first request. The exact integration depends on your Cypress version and bundler.
Troubleshoot requests and polyfill setup
The old option errors or does nothing
Remove experimentalFetchPolyfill from Cypress configuration. It is no longer a supported setting; use cy.intercept() for test network handling. See the migration guidance.
Rank #4
The intercept does not fire
- Register the intercept before the action that causes the request.
- Check that the method and URL matcher correspond to the actual request.
- Check browser caching. Cypress notes that a response served from the browser cache does not reach the network layer, so
cy.intercept()will not fire for it. See the intercept documentation.
Fetch fails from Electron’s initial about:blank
Cypress documents that Electron does not permit fetch or XMLHttpRequest from the initial about:blank page before navigation. Use cy.request() for a direct Cypress-side request, or navigate first with cy.visit(). This is distinct from an application request after the AUT has loaded. See Cypress cy.request() documentation.
The polyfill import appears ineffective
Confirm that the import executes before application code and changes the AUT’s window, rather than only affecting Cypress test setup. The support bundle and AUT are separate contexts; consult the integration instructions for your project’s version and bundler.
Recommended Free Tools
Or skip the browser setup
For a screenshot of a rendered page, ScreenshotNeo provides a one-request alternative to setting up browser automation. See the ScreenshotNeo API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
ScreenshotNeo accepts cookie or consent banners before capture and removes known consent platforms, newsletter popups, and chat widgets; those cleanup steps can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed. It also offers an MCP server for AI agents to take screenshots, and the free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000.
Learn about ScreenshotNeo, or sign up for 1,000 free screenshots a month with no card.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

