Cypress: cy.visit() Failed Trying to Load the Page

10 min readupdated September 10, 2026

The very first line of your test fails:

CypressError: cy.visit() failed trying to load:
http://localhost:3000/

We attempted to make an http request to this URL but the request failed
without a response.

Nothing has run yet. Cypress could not even open the page.

The good news is that this error is honest. It really did fail to fetch that URL, and there is a short list of reasons. Work down it in order and you will usually find the cause in a couple of minutes.

Start here: can you fetch it yourself?

Before touching Cypress, run this in a terminal with the exact URL from the error:

curl -I http://localhost:3000/

That single command splits the problem in half.

No response at all? The problem is your server or the URL. Causes 1 to 3.

A response, but not a 2xx? The problem is the status code. Cause 4.

A normal 200? The problem is inside Cypress or the page itself. Causes 5 onward.

Cause 1: The server is not running

By far the most common, and the least interesting.

Cypress does not start your application. It expects it to already be there. Running npx cypress open in one terminal while forgetting npm run dev in another is something everyone does at least once.

In CI this becomes its own class of bug: the pipeline starts the app and the tests in the same step, and the tests win the race. Start the server, wait for it to answer, then run the tests. Do not sleep for a fixed number of seconds and hope.

Cause 2: The wrong port or the wrong host

Your app runs on 5173 and baseUrl says 3000. Or the app moved to another port because the first was taken, and printed that in a log nobody read.

Check the URL in the error against what your dev server actually printed.

// cypress.config.js
module.exports = defineConfig({
  e2e: {
    baseUrl: 'http://localhost:5173',
  },
});

Inside Docker or CI, localhost may not mean what you expect. A container's localhost is the container itself, not the host machine or a sibling service. Use the service name your network provides.

Cause 3: HTTP against HTTPS, or a bad certificate

Visiting http:// when the server only speaks https:// fails without a useful message. So does a self-signed certificate on a local environment.

For a local environment with a self-signed certificate, and only there:

module.exports = defineConfig({
  chromeWebSecurity: false,
});

Use that knowingly. It turns off a browser security model, it works only in Chrome-based browsers, and it should never follow you into a shared config.

Cause 4: The page returned a non-2xx status

This one surprises people, because the page loads fine in a browser.

Cypress treats any status outside the 2xx range as a failure. A 401, a 403, a 404 or a 500 all fail cy.visit() even though the server responded correctly.

Often that is exactly what you want. Sometimes it is not: you may be deliberately testing a 404 page, or hitting a route that returns 401 before you log in.

cy.visit('/admin', { failOnStatusCode: false });
cy.contains('Please sign in').should('be.visible');

If your app is behind basic auth:

cy.visit('/', { auth: { username: 'demo', password: 'secure123' } });

Only reach for failOnStatusCode: false when you mean it. Turning it on globally hides real breakage.

Cause 5: The page never fired its load event

Cypress waits for the page's load event. If that never fires, you get a timeout rather than a connection failure.

Timed out after waiting 60000ms for your remote page to load.

A slow first compile in development is the usual cause, and a request that never resolves is the interesting one. An asset or an API call that hangs forever will hold the load event open indefinitely.

Raising the limit is reasonable for a genuinely slow first build:

module.exports = defineConfig({
  pageLoadTimeout: 120000,
});

But check the network tab first. A pending request that never completes is a real bug, and raising the timeout just makes you wait longer to find it.

Cause 6: The page redirects to another origin

You visit your app, and it bounces to an identity provider on a different domain. Cypress runs inside the browser, so it obeys the same-origin policy and cannot follow.

That needs cy.origin(), and this guide covers it, including the trap that the callback is not a closure.

Cause 7: ESOCKETTIMEDOUT and other network errors

cy.visit() failed trying to load: ESOCKETTIMEDOUT

The connection opened and then stalled. Usually a proxy, a VPN, or a corporate network intercepting traffic. If your machine needs a proxy to reach the target, Cypress needs to know about it through the standard HTTP_PROXY and HTTPS_PROXY environment variables.

Cause 8: The app crashed while loading

The server is up, the URL is right, and the page throws during startup. A missing environment variable in the test environment is the classic reason.

Open the URL yourself in a normal browser and look at the console. If the app is broken, your test found a real bug on its very first line.

Cause 9: Visiting a file instead of a URL

cy.visit('index.html');       // not a URL
cy.visit('/index.html');      // relative to baseUrl, probably not what you want

Without baseUrl set, a relative path has nothing to resolve against. Set baseUrl, then use paths relative to it.

Quick reference

The error says Likely cause First check
Request failed without a response Server not running, wrong port curl -I the URL
Expected 200, got 401 or 403 Auth required auth option or failOnStatusCode
Expected 200, got 404 Wrong path Check the route exists
Timed out waiting for the page to load A request that never resolves Network tab
ESOCKETTIMEDOUT Proxy or VPN Proxy environment variables
Cross origin error on load A redirect to another domain cy.origin()

Common mistakes

  1. Raising pageLoadTimeout first. If a request hangs forever, no timeout is long enough.
  2. Setting failOnStatusCode: false globally. That hides every broken page in the suite.
  3. Sleeping instead of waiting for the server in CI. Poll the URL until it answers.
  4. Assuming localhost works in Docker. Inside a container it means the container.
  5. Not opening the URL yourself. Thirty seconds in a browser answers most of this.

Frequently asked questions

Why does the page load in my browser but not in Cypress? Most often a non-2xx status, which your browser renders happily and Cypress treats as a failure. Check with curl -I.

Should I use failOnStatusCode: false? Only for a specific visit where a non-2xx response is what you are testing. Never globally.

Why does this only fail in CI? Usually the app is not ready yet. Wait for the URL to answer rather than sleeping.

Cypress says it cannot verify the server is running. Same thing? Same family. Cypress could not reach baseUrl. Start with curl.

Remember this

This error is literal. Cypress asked for a URL and did not get a page it would accept.

Run curl -I on the exact URL from the error before anything else. No response means your server or your URL. A non-2xx means the status code, and failOnStatusCode if that status is the point. A clean 200 means the problem is the page itself or an origin redirect.

Raising the timeout is the last move, not the first.

The Cypress tutorial covers baseUrl and the rest of the config this error usually comes down to.

Put it into practice

Solve a graded problem: write a test, and we check it would catch a real bug.

Browse the problems →

Learn this in full

Reading about a problem is not the same as fixing one. Pick a lecture or a practice problem and write the test yourself.

Keep reading