Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
A Cypress load-event timeout on GitHub Actions usually means the browser never saw the page finish loading before Cypress’s deadline—not simply that a test needs a longer wait. Start the app in the workflow, verify the exact URL Cypress will visit is reachable, and inspect the page for slow or failed resources. Increase pageLoadTimeout only when those checks show that a healthy page is predictably slow.
What a Cypress load-event timeout means
cy.visit() waits for the browser’s document load event before it resolves. Receiving the initial HTML response is not enough: the event can be held up by resources such as scripts, stylesheets, and images. If it does not fire before Cypress’s timeout, the visit fails.
Cypress documents a default pageLoadTimeout of 60,000 ms. That is different from defaultCommandTimeout, which defaults to 4,000 ms and applies to most DOM commands. A page-load timeout points first to startup, routing, redirects, browser resource loading, or navigation—not necessarily to a slow element query.
Fix server readiness before changing Cypress timeouts
A common CI-only cause is that the test starts before the application is ready. A process may have been launched without successfully listening on its port, or the application may need longer to initialize in the runner than on a developer’s machine. Configure the Cypress GitHub Action to start the app and poll a URL that is reachable from the job.
#1 Best Overall
- uses: cypress-io/github-action@v7
with:
start: npm start
wait-on: 'http://localhost:8080/health'
wait-on-timeout: 120
The action’s default wait-on retry period is 60 seconds. Set wait-on-timeout in seconds if startup is known to take longer. Choose a health endpoint that indicates the app is actually ready to serve the page under test; a process merely existing is not proof that the browser can load the application.
Verify the endpoint from inside the workflow
Use the same host, protocol, port, and path that the Cypress browser will use. A URL that works on your laptop may not resolve from the GitHub Actions runner, particularly if it refers to a local service or hostname that only exists in another environment. Probe the endpoint in the job before Cypress starts; the official action also provides a ping diagnostic pattern with two retries. This makes a connection or path problem visible earlier than a browser timeout.
Make the URL Cypress visits explicit
Set e2e.baseUrl to the address available inside the runner, including its protocol and port. When a test calls cy.visit('/'), Cypress prefixes that relative path with baseUrl. A mismatch can send the browser to a wrong host, an unintended route, or a redirect path that never reaches the expected page.
import { defineConfig } from 'cypress';
export default defineConfig({
e2e: {
baseUrl: 'http://localhost:3000',
pageLoadTimeout: 60000,
},
});
Use the host and port that are reachable from the runner. If the test visits a different origin directly, check that URL independently rather than assuming baseUrl governs it. Confirm redirects, authentication, and cross-origin transitions behave as expected in CI.
Rank #2
Inspect the page and its resources
If the server is reachable and the configured URL is correct, inspect the failed page in the CI browser artifacts and review Cypress and action logs. Look for failed or indefinitely pending requests, certificate errors, redirect loops, authentication failures, and calls to dependent services unavailable from the runner. A resource that never completes can prevent the browser’s load event even when the main HTML rendered.
- Check whether the failing URL returns the expected HTML response from the runner.
- Identify requests that fail, remain pending, or are redirected unexpectedly.
- Confirm the application’s required APIs and services are reachable in the workflow environment.
- Compare the CI browser console and server logs with a successful local run, if available.
Do not treat a visually rendered page as proof that navigation completed successfully: Cypress is waiting for the browser event, not just for content to appear.
Use the narrowest timeout that addresses the cause
After confirming the page is healthy but predictably slower in CI, raise pageLoadTimeout to a measured value. For example, 100,000 ms can be set in the Cypress configuration, passed through the GitHub Action’s config input, or supplied to a particular visit.
// cypress.config.js or cypress.config.ts
export default {
e2e: {
pageLoadTimeout: 100000,
},
};
// GitHub Actions input
config: baseUrl=http://localhost:3000,pageLoadTimeout=100000
// One navigation only
cy.visit('/', { timeout: 100000 });
Prefer the per-visit setting when only one known navigation needs more time; use global configuration when the measured behavior applies across the suite. A larger timeout does not bypass operating-system network limits. It also means a genuinely stuck navigation can occupy the job longer, so do not increase it blindly or use it in place of diagnosing failures.
Rank #3
Wait for application requests with routes and assertions
A page can finish its browser load event before its application has received the data a test needs. That is a separate synchronization problem. Register intercepts before navigation, alias the relevant requests, and wait for those routes or assert against the resulting UI.
cy.intercept('GET', '/api/products').as('getProducts');
cy.visit('/products');
cy.wait('@getProducts');
cy.get('[data-testid="product-list"]').should('be.visible');
Set the matcher to the actual request URL or pattern used by your app. Intercepts registered after cy.visit() can miss requests made during page startup. Cypress does not provide a magical wait for all XHR or Ajax requests; choose the specific request that matters to the test.
A fixed delay such as cy.wait(3000) is usually slower and less reliable: it may be longer than necessary on one run and too short on another. A retryable assertion expresses the condition the test needs and lets Cypress retry it within the command timeout.
Use a complete GitHub Actions pattern
This example starts the application, waits for its health endpoint, sets the browser base URL and a measured page-load limit, enables action-level debug logging, and bounds the job. Adapt the start command and URLs to the app and runner rather than copying localhost values that do not match your setup.
Rank #4
jobs:
cypress:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: cypress-io/github-action@v7
with:
start: npm start
wait-on: 'http://localhost:3000'
wait-on-timeout: 120
config: baseUrl=http://localhost:3000,pageLoadTimeout=100000
env:
DEBUG: '@cypress/github-action'
Use a workflow timeout-minutes as a safety bound so a hung process cannot consume CI minutes indefinitely. It limits the job; it does not repair the navigation failure. Likewise, allowing more time for app readiness and allowing more time for cy.visit() address different stages, so tune each only when evidence points to that stage.
Turn on logs and preserve useful artifacts
For action-level diagnostics, set DEBUG to @cypress/github-action. For broader Cypress logs, use DEBUG set to cypress:*. GitHub Actions step debugging can be enabled by setting the ACTIONS_STEP_DEBUG secret or variable to true.
Preserve screenshots, videos, browser console output, and server logs as workflow artifacts when possible. Those records help distinguish a server that never became ready from a browser navigation blocked by one failed resource. Enable only the logging and artifact collection useful to your investigation, since verbose output can make logs harder to scan.
Troubleshoot by symptom
| Symptom | Likely layer | What to check or change |
|---|---|---|
| Cypress fails immediately or the app URL cannot be reached | Server readiness or network | Confirm start launches the service; poll the exact URL with wait-on; verify host, port, protocol, and path from the runner. |
| The browser reaches a different page or keeps redirecting | URL, routing, or authentication | Set the correct e2e.baseUrl; inspect redirects and authentication behavior for the CI environment. |
| The page appears but the visit still times out | Resource loading or navigation | Inspect the browser console and network activity for requests that failed or never completed, including scripts, stylesheets, images, and dependent services. |
| The visit succeeds but an element or data is missing | Post-load application request | Register cy.intercept() before visiting, wait on the relevant alias, and assert on the rendered state. |
| The page is consistently healthy but slow in CI | Measured navigation duration | Raise only pageLoadTimeout to an observed value; keep a workflow-level timeout bound. |
| The failure is difficult to reproduce | Insufficient observability | Enable action or Cypress debug logs and retain browser and server artifacts for failed runs. |
Or skip the browser setup
If the goal is to obtain a screenshot of a public page rather than run a Cypress browser test, ScreenshotNeo provides a screenshot API and MCP server. This does not fix a Cypress test or replace validating your app inside GitHub Actions; it is an alternative for screenshot capture. The API accepts a URL in one GET request and can return PNG, JPEG, WebP, or PDF. Its cleanup steps accept cookie and consent banners and remove more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status in headers. AI agents can use its MCP tools, including take_screenshot, get_page_info, and capture_pdf.
For API parameters and options, see the ScreenshotNeo documentation. Replace the example URL with the page you want to capture and supply your API key:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Sign up for ScreenshotNeo’s free plan to try it without a card.
Keep the fix reliable and the CI cost bounded
Longer waits and retries can add CI time, especially when a dependency is slow on every run. Fixing readiness or a broken resource is better than extending the deadline for every test. Use targeted request waits for data synchronization, a narrowly scoped navigation timeout for a genuinely slow page, and a workflow timeout as the final bound. This keeps failures diagnostic: a server-start problem should fail at readiness, while a page-load problem should surface during navigation.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Frequently Asked Questions
Should I increase defaultCommandTimeout to fix this error?
Usually not. It controls most DOM commands, while the navigation deadline is pageLoadTimeout. Change the setting that matches the stage where the failure occurs.
Does wait-on prove every page resource will finish loading?
No. It checks whether the configured URL becomes available; Cypress can still time out later if navigation resources do not complete.
Can I use a network-idle wait instead of route aliases?
The relevant test condition is usually a specific request or UI state. Alias that request and assert on the resulting state rather than waiting on an arbitrary delay.
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.

