Cypress vs Selenium: An Honest Comparison for 2026

16 min readupdated September 10, 2026

Most comparisons of these two read like a feature list, and feature lists do not help you choose. Almost everything that matters comes from one design decision, and once you know it you can predict the rest yourself.

If you want Playwright in the picture too, the three-way comparison is here.

Cypress runs inside the browser, in the same window as your app. Selenium drives the browser from outside, over a standard protocol.

That is the whole story. Everything below follows from it.

The short answer

You are... Choose
A JavaScript team testing one web app Cypress
A Java, Python, C# or Ruby team Selenium
Testing flows across tabs or domains Selenium
Testing real Safari Selenium
Testing components as well as pages Cypress
Learning automation from scratch Cypress, for the debugger
Starting a new JavaScript project today Read the last section first

What is Cypress?

Cypress is an open-source testing tool for web applications, first released in 2017. It bundles a test runner, an assertion library and automatic waiting into a single install, so there is nothing to wire together.

Its defining feature is where your test code runs. It executes inside the browser, in the same event loop as your application, rather than in a separate process talking to the browser.

Advantages

  • The best interactive debugger of any browser automation tool.
  • Waits automatically, so a beginner's first test is usually stable.
  • One install gives you everything. No framework assembly required.
  • Direct control of network traffic through cy.intercept().
  • Component testing for React, Angular, Vue and Svelte.

Limitations

  • JavaScript and TypeScript only.
  • One tab per test.
  • Cross-origin work needs cy.origin().
  • Safari support is experimental, in Cypress's own wording.
  • Parallel orchestration in CI is a paid product.

What is Selenium?

Selenium is the oldest of the major browser automation tools, in use since 2004. It is not really a framework. It is a library that speaks WebDriver, a W3C standard that browser makers implement themselves.

That standing is the point. Selenium is not a product that a company can discontinue. It is a specification with implementations, which is why it reaches further than anything else.

Advantages

  • The widest language support: Java, Python, C#, JavaScript, Ruby and Kotlin.
  • The widest browser support, including real Safari through Apple's own driver.
  • No tab, window or origin restrictions.
  • A W3C standard, which matters for long-lived or regulated projects.
  • The largest pool of experienced engineers and the most job postings.

Limitations

  • No automatic waiting. You write the waits.
  • No test runner, assertions, config or reporting. You assemble those.
  • More code for the same result.
  • Every command is a round trip to a driver process.

The same test in both

One scenario: sign in, then check the welcome message.

Cypress

describe('Login', () => {
  it('signs in with valid details', () => {
    cy.visit('/');
    cy.get('[data-testid="email"]').type('demo@nimbus.app');
    cy.get('[data-testid="password"]').type('secure123');
    cy.get('[data-testid="submit"]').click();
    cy.get('[data-testid="welcome-message"]').should('contain.text', 'Welcome back');
  });
});

Selenium (JavaScript)

const { By, Builder, Browser, until } = require('selenium-webdriver');
const assert = require('assert');

(async function loginTest() {
  let driver;
  try {
    driver = await new Builder().forBrowser(Browser.CHROME).build();
    await driver.get('http://localhost:3000/');

    await driver.findElement(By.css('[data-testid="email"]')).sendKeys('demo@nimbus.app');
    await driver.findElement(By.css('[data-testid="password"]')).sendKeys('secure123');
    await driver.findElement(By.css('[data-testid="submit"]')).click();

    const welcome = await driver.wait(
      until.elementLocated(By.css('[data-testid="welcome-message"]')),
      5000,
    );
    assert.ok((await welcome.getText()).includes('Welcome back'));
  } finally {
    await driver.quit();
  }
}());

Three differences are visible immediately.

Cypress is shorter, because the runner, the assertions and the waiting come with it.

Selenium is explicit. You start the driver, you wait for what you need, you quit in a finally block. Skip that last part and you leak browser processes until the machine runs out of memory.

Cypress never awaits. Commands queue and run in order. Selenium awaits everything, because each command is a real promise.

The comparison table

Topic Cypress Selenium
Runs Inside the browser Outside, via WebDriver
Style Command chain, no await Explicit, language native
Languages JS/TS only Java, Python, C#, JS, Ruby, Kotlin
Chromium and Firefox Yes Yes
Safari Experimental WebKit only Yes, real Safari on macOS
Multiple tabs No Yes
Multiple origins Via cy.origin() Yes
Auto-waiting Yes No, you write waits
Test runner included Yes No
Assertions included Yes No
Network mocking cy.intercept() WebDriver BiDi
Component testing Yes No
Parallel runs Paid orchestration Grid, self-hosted
Debugging Time-travel runner Standard debugger
First release 2017 2004

What running inside the browser buys Cypress

It feels fast, and the debugging is genuinely better than anything else. Cypress sits next to your application, so it can see the page directly with no round trip to another process. That makes retrying every command cheap, which is why Cypress can wait for things automatically without you asking.

It also produces the feature people miss most when they leave: a command log you can hover, showing the page at that moment in the test. When a test fails at step nine, you can look at step seven. For someone learning automation, this shortens the feedback loop enormously.

You write less setup. Cypress ships a test runner, an assertion library, and its waiting behaviour in one install. There is nothing to wire together.

What running outside the browser buys Selenium

Reach, and it is not close. Selenium is built on WebDriver, a W3C standard that browser makers implement themselves. That means Selenium works with more browsers, more languages and more operating systems than anything else.

If your team writes Java, this is decisive on its own. A Java team will maintain a Java suite far better than a JavaScript suite nobody is comfortable in, and that matters more over three years than any feature.

No same-origin restriction, and no tab limit. Because Selenium is not page code, the browser's page-level security rules do not apply to it. Multiple tabs, multiple domains and multiple windows are ordinary work.

Waiting: the biggest day-to-day difference

If you only compare one thing, compare this. It decides how much of your week goes into maintenance.

Cypress retries. A command or assertion that does not succeed immediately is tried again until it passes or the timeout is reached. You rarely write a wait.

cy.get('[data-testid="submit"]').click();
cy.get('[data-testid="toast"]').should('be.visible'); // retries on its own

Selenium does not. You decide what to wait for:

await driver.findElement(By.css('[data-testid="submit"]')).click();
const toast = await driver.wait(
  until.elementLocated(By.css('[data-testid="toast"]')),
  5000,
);
await driver.wait(until.elementIsVisible(toast), 5000);

That is more code, and it is more control. Nothing waits behind your back.

It is also the reason so many older Selenium suites are full of Thread.sleep and driver.sleep. When waiting is your job and you are in a hurry, a sleep is the tempting shortcut. It is also the single biggest cause of slow, flaky suites. Selenium is not unreliable. Sleeps are. Fixing flaky tests goes through the causes.

Browser support, precisely

This is where comparison articles get vague, so here it is exactly.

Cypress properly supports Chrome-family browsers, including Edge, and Firefox. Its WebKit support is described in Cypress's own documentation as experimental, and it is built on Playwright's WebKit. Cypress does not drive Safari itself.

Selenium drives Chrome, Firefox, Edge and real Safari, through Apple's own SafariDriver on macOS. It is the only one of the major tools that does.

If your contract says "must work in Safari" and means the actual browser, that decides it.

Language support

Cypress is JavaScript and TypeScript. That is the whole list.

Selenium covers Java, Python, C#, JavaScript, Ruby and Kotlin, with Java and Python having the deepest ecosystems.

This is the most under-weighted factor in most comparisons and often the most important one. A suite is maintained for years by whoever is on the team. A Java team handed a JavaScript suite will maintain it badly, and no feature makes up for that.

Debugging

Cypress wins the interactive loop, clearly. The runner lists every command as it executes. Hover a step and the app snaps back to that moment. Click a step and the details go to the console, including what the selector matched. For learning what your test is actually doing, nothing else is as immediate.

Selenium has no equivalent built in. You use your language's debugger, screenshots on failure, and whatever reporting your team assembled. It works, and it is more effort.

Network control and mocking

Because Cypress lives in the browser, it sees network traffic directly, and cy.intercept() is one of its best features:

cy.intercept('GET', '**/api/contacts', { statusCode: 500 });
cy.visit('/contacts');
cy.contains('Something went wrong').should('be.visible');

Faking a server error in two lines is the only practical way to test unhappy paths.

Selenium historically had no answer here, which is a real reason teams left. That has changed. WebDriver BiDi brings network interception, request mocking, console capture and JavaScript error listening to Selenium as a cross-browser standard, and recent releases have been rolling it out across the language bindings. It is newer and less polished than cy.intercept(), and it closes a gap that used to be decisive.

Component testing

Not close. Cypress mounts React, Angular, Vue and Svelte components in a real browser and tests them in isolation. Selenium has nothing comparable, because it drives browsers rather than mounting components.

If you want one tool for both component and end-to-end tests, that is a genuine reason to pick Cypress.

Parallel runs, Grid and cost

Both tools are free and open source. The money question is what happens in CI.

Cypress splits work by spec file. Running specs in parallel locally is free. Splitting a suite across CI machines with balanced timing and a merged report is Cypress Cloud, which is paid above a free tier. For a five-minute suite this never comes up. For a forty-minute suite it becomes a budget line.

Selenium parallelises through Grid, which you host. Free to run, and it costs your team's time to maintain, which is rarely zero. Hosted grids from other vendors are paid.

Neither is cheaper in the abstract. One spends money, the other spends engineering hours.

The limits you should know before choosing

These are the Cypress ones, and they are all predictable from "it runs inside the browser":

  • One tab. A test cannot drive a second tab, because a tab cannot control another tab. Usually you check the link's target attribute instead.
  • Cross-origin needs care. Your test is page code, so it obeys the same-origin policy. cy.origin() handles this and works, but it is extra machinery, and it is painful as a general pattern rather than for one login test.
  • Safari support is experimental. If a large part of your traffic is iPhone users, that matters.
  • Free parallel running is limited. The good load balancing is a paid product.

And the Selenium ones, which all come from "it is a library, not a framework":

  • You build the framework. Selenium gives you browser control. No test runner, no assertions, no configuration, no reporting, and no automatic waiting. Every Selenium team writes those layers, and writing them badly is the usual reason a Selenium suite is unreliable.
  • Waiting is your job. This is the single biggest source of flaky Selenium tests, and nothing in the tool stops you skipping it.
  • It is structurally slower. Every command is an HTTP round trip to a driver process. On your laptop that is a millisecond. To a remote Grid it can be 30ms, and a chatty test pays it hundreds of times.

One myth worth correcting: driver version mismatches are mostly solved. Modern Selenium ships Selenium Manager, which finds and fetches the right driver for you. If you read a tutorial telling you to download ChromeDriver by hand and set a PATH variable, it predates that. If you do still hit it, this guide explains it.

Speed, honestly

Cypress usually feels faster, and for a single test on one machine it often is. But at suite scale the picture changes: a well-built Selenium suite with proper parallel Grid capacity can finish a large run quickly, and a badly built Cypress suite that logs in through the form for every test will be slow no matter what.

The honest summary: the tool sets your floor, your setup decides your actual runtime. Most slow suites are slow because of user-interface setup and missing parallelism, not because of the tool.

Treat benchmark numbers in vendor blog posts with suspicion. They compare a tuned version of one tool against a naive version of the other.

Learning curve

Cypress is faster to a first working test, by a wide margin. Install, open, write six lines, watch it run in the time-travel runner.

Selenium takes longer, because you have to choose a test runner, an assertion library and a reporting approach before you have written anything. That work pays back on a large suite and feels like an obstacle on day one.

There is one Cypress concept that catches everybody: commands queue rather than execute, so you never await them and you cannot assign one to a variable. Get past that and the rest is straightforward. The Cypress tutorial covers it properly.

Job market

Selenium still appears in more QA automation postings than any other tool, especially in enterprise, finance and anything Java-heavy. Cypress is common at product companies with JavaScript front-end teams.

The useful thing to know is that the concepts transfer. Locators, waiting, assertions and test isolation are the same job in both. Someone fluent in one picks up the other in days, so treat this as a tiebreaker rather than a decision.

Which should you choose?

Choose Cypress when:

  • Your team writes JavaScript or TypeScript and will maintain the tests themselves.
  • You are testing one web application, in one tab, on Chromium and Firefox.
  • You want the shortest path from nothing to a working test, and the best debugging experience while learning.
  • You want to test components as well as pages.

Choose Selenium when:

  • Your team does not write JavaScript. This is the strongest reason on the list.
  • You need real Safari, older browsers, or platforms other tools do not reach.
  • Your flows cross tabs or domains routinely.
  • You already have a large, working suite that catches real bugs. That has value a rewrite would destroy for months.
  • Your organisation needs a long-lived standard for compliance reasons. Selenium's age and its W3C standing are advantages there.

Migrating between them

Rarely worth it on its own. A rewrite spends months to arrive back at the coverage you already had, and the coverage is the asset, not the syntax.

Migrate when you can name the limit you are hitting. "Our checkout redirects to a payment provider and Cypress cannot follow it" is a reason. "Selenium feels old" is not.

If you do move, run both suites side by side, write new tests in the new tool, and port old ones only when you touch them.

The answer people do not expect

If you are starting fresh in 2026 with a JavaScript team, the honest recommendation is often neither of these two: look at Playwright first.

It runs outside the browser like Selenium, so it has no tab or origin limits. It waits automatically like Cypress, so waiting is not your job. It runs Chromium, Firefox and WebKit, and its parallel running is free and built in.

That does not make Cypress or Selenium wrong. A working suite is worth more than a better tool, and migrating costs months to arrive at the coverage you already had. But if nothing is written yet, comparing only these two is comparing the wrong pair.

We teach all three here for that reason, and the ideas move across: locators, waiting, assertions and test data are the same job in every tool. Only the words change.

Frequently asked questions

Is Cypress better than Selenium? For a JavaScript team testing one web app, usually yes, because it is faster to write and easier to debug. For anything needing other languages, real Safari, or multiple tabs, Selenium is the better fit.

Is Selenium dead? No. It has the widest language and browser support, it drives real Safari, and it appears in more job postings than any other tool. Selenium Manager and WebDriver BiDi have also closed two of the oldest complaints about it.

Which is faster, Cypress or Selenium? Cypress is usually faster for a single test, because it avoids a round trip per command. At suite scale, parallelism and how you set up test data matter far more than the tool.

Can Cypress test multiple tabs? No. Cypress runs inside one browser tab. This is the clearest structural limit it has.

Can Cypress test more than one domain? Yes, with cy.origin(). The flat claim that it cannot is out of date, though it is more work than in Selenium.

Do I still need to download ChromeDriver for Selenium? No. Selenium Manager is built in and fetches the matching driver automatically.

Which should I learn first as a beginner? Cypress, if you write JavaScript, because the debugger teaches you what your test is doing. Selenium if you are targeting Java or enterprise roles, because that is what those postings ask for.

Can I use both? Yes, and teams sometimes do during a migration. The concepts transfer almost one to one.

Remember this

Cypress trades freedom for a great developer experience. Selenium trades convenience for reach. Choose for your constraints, your team's language and the app you actually have, not for whichever tool a comparison article liked most.

Next: read the Cypress tutorial or the Selenium WebDriver tutorial, then write a real test in the practice editor and see which one you prefer working in.

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