Cloud & Infrastructure
Selenium
The long-established, W3C-standard way to drive real browsers — used with the discipline it demands, and honest about when a newer tool would serve you better.
Overview
Selenium is the open-source standard for automating real web browsers. At its core is WebDriver — now a W3C specification rather than a bolt-on — which gives a common protocol for driving Chrome, Firefox, Safari and Edge as an actual user would: clicking, typing, navigating and reading what the page renders. That is its defining characteristic and its enduring value. You are not testing an approximation of a browser or a headless shell that behaves differently from the real thing; you are exercising the same rendering engine your customers use, which is why Selenium remains the reference point for genuine cross-browser coverage.
Around that protocol sits an ecosystem few tools can match. Selenium ships official bindings for Java, Python, C#, JavaScript and Ruby, so a team writes tests in the language it already works in rather than adopting a new one. Selenium Grid distributes runs across browsers and machines so a suite that would take an hour in series finishes in minutes in parallel. And because Selenium has been the standard for well over a decade, almost every CI system, reporting tool, cloud device farm and test framework integrates with it out of the box. The same longevity means a vast body of documentation, answered questions and engineers who already know it.
We use Selenium for what it is genuinely good at: building maintainable, CI-integrated end-to-end test suites that verify a web application really works across the browsers your users run, and driving browser automation where real-browser fidelity or broad browser support matters. Where we differ from a lot of shops is that we are blunt about the trade-off. Selenium is powerful, but its tests are notoriously prone to flakiness, it is relatively slow, and it only becomes reliable through disciplined engineering — explicit waits, the Page Object Model, and stable selectors. For many new E2E suites, Playwright or Cypress is simply the better tool, and we will tell you so before you commit.
Best for — Maintainable, CI-integrated end-to-end tests where broad real-browser coverage or a specific language stack matters — and where a senior team will supply the waiting discipline and structure Selenium needs to stay reliable.
Why teams choose Selenium
Real browsers, real coverage
Selenium drives the actual Chrome, Firefox, Safari and Edge engines through the W3C WebDriver protocol, so your tests catch the rendering and behaviour differences your customers would hit. This is coverage no headless approximation gives you, and it is the strongest reason Selenium still earns its place.
Write tests in your language
Official bindings for Java, Python, C#, JavaScript and Ruby mean the test suite lives in the same language as your team. Your engineers reuse skills, share tooling, and are not forced into a JavaScript-only world just to test — a genuine advantage for teams built on the JVM or .NET.
Parallel runs that fit your pipeline
Selenium Grid distributes tests across browsers and machines, turning a suite that runs for an hour in series into one that finishes in minutes. Combined with mature CI integration, it makes broad cross-browser testing fast enough to run on every change rather than overnight.
Why businesses choose Selenium
- You need broad, genuine cross-browser coverage — including Safari and older or enterprise browsers — that newer tools do not match.
- Your team is invested in Java, C# or another non-JavaScript stack and wants its tests to live in the same language.
- You already run a substantial Selenium suite and want it made reliable, faster and properly integrated into CI rather than rewritten.
- You want a partner who will apply Selenium’s required discipline — explicit waits, page objects, stable selectors — or tell you honestly when Playwright or Cypress would serve you better.
What we build with Selenium
The capabilities this technology is genuinely strong at — and what we most often build with it.
W3C WebDriver protocol
Selenium drives browsers through WebDriver, now a W3C standard, which sends commands to the real browser via its own driver — chromedriver, geckodriver and the rest. Understanding that this is a genuine remote-control protocol, not an in-process hook, explains both Selenium’s real-browser fidelity and its latency, and is the foundation everything else builds on.
Explicit waits over implicit ones
The single biggest cause of Selenium flakiness is code that acts before the page is ready. We use explicit waits — WebDriverWait with expected conditions — to wait for the specific state a step depends on, and avoid the blunt implicit waits and hard-coded sleeps that make suites either slow or unreliable. Disciplined waiting is what separates a trustworthy Selenium suite from an ignored one.
The Page Object Model
We structure suites around the Page Object Model, so the selectors and interactions for each screen live in one class behind a clean interface. When the UI changes, you fix one page object rather than a hundred scattered tests. This pattern is not optional at scale — it is the difference between a maintainable Selenium suite and an unmaintainable one.
Stable, resilient selectors
Tests break when they hang off fragile locators — deep CSS paths or auto-generated classes that change with every build. We anchor on stable hooks, ideally dedicated test identifiers agreed with the developers, so a cosmetic change to the markup does not turn the suite red. Selector strategy is a design decision we make deliberately, not an afterthought.
Selenium Grid for parallel, distributed runs
Grid lets tests run in parallel across multiple browsers and machines, whether self-hosted or on a cloud provider. We configure it so a full cross-browser suite completes fast enough to gate every merge, and design tests to be independent and stateless so they can run concurrently without interfering with one another.
Multi-language bindings
Selenium offers official bindings for Java, Python, C#, JavaScript and Ruby over the same WebDriver protocol. We write the suite in the language that fits your team and pair it with the right test runner — JUnit or TestNG, pytest, NUnit — so the tests feel native to your stack rather than bolted on beside it.
Use cases
CI-integrated end-to-end regression
A suite that verifies the critical user journeys of a web application on every merge, running in CI across the browsers your users actually use, so regressions are caught before release rather than by customers.
Cross-browser compatibility testing
Confirming that a feature behaves the same in Chrome, Firefox, Safari and Edge — including the older or enterprise-mandated versions that modern tools do not cover — where real-engine fidelity is the whole point.
Rescuing a flaky existing suite
Taking an inherited Selenium suite that everyone has stopped trusting and making it reliable: introducing explicit waits, refactoring to page objects, stabilising selectors, and getting it running green and fast in the pipeline.
Browser automation and data collection
Driving real browsers for automation and scraping where a page depends on JavaScript rendering or complex interaction — automating repetitive web workflows, or gathering data that a simple HTTP request cannot reach.
When Selenium is the right choice
- Right when you need genuine cross-browser coverage — Chrome, Firefox, Safari and Edge, including older or enterprise-mandated browser versions — because Selenium drives the real engines and its browser support is broader than any newer alternative.
- Right when your team wants to write tests in a specific language — Java, C#, Python, Ruby — and keep the test suite in the same stack as the rest of your engineering, rather than being pushed into JavaScript or TypeScript by the tool.
- Right when you already have a substantial Selenium investment that works: a large, well-maintained suite is an asset, and rewriting it into another framework is rarely worth the cost just to follow fashion.
- Wrong for a brand-new E2E suite on a modern web app where the team is comfortable in JavaScript or TypeScript. Playwright and Cypress give you auto-waiting, better speed, less flakiness and a far better developer experience out of the box — for most new projects they are the better starting point, and we will say so.
- Wrong when a team wants automated testing without owning the discipline it requires. Selenium punishes shortcuts: without explicit waits, page objects and stable selectors, you get a slow, flaky suite that everyone learns to ignore. If nobody will maintain it properly, it is worse than no suite at all.
Selenium: pros and cons
Strengths
- Drives real browsers across the widest range — Chrome, Firefox, Safari, Edge and older versions — for the most genuine cross-browser coverage available.
- W3C-standard WebDriver protocol and multi-language bindings (Java, Python, C#, JavaScript, Ruby) let teams test in the stack they already use.
- Enormous, mature ecosystem: Selenium Grid for parallel runs, deep CI integration, cloud device farms, reporting tools, and more than a decade of documentation and answered questions.
- A huge hiring pool and body of existing knowledge — finding engineers who already know Selenium is easier than for any newer testing tool.
Trade-offs
- Notoriously prone to flakiness: without carefully placed explicit waits, tests race the browser and fail intermittently for timing reasons that have nothing to do with real bugs, eroding trust in the whole suite.
- Relatively slow compared with modern alternatives, and it does more setup — drivers, browser versions, grid configuration — before a single test runs, which adds friction to getting started and keeping running.
- High maintenance burden: brittle selectors break on UI changes, and keeping a large suite green demands ongoing engineering discipline that teams routinely underestimate.
- A worse developer experience than Playwright or Cypress for new suites — no built-in auto-waiting, less helpful debugging, and more boilerplate — which is why those tools are often the better choice for a fresh start.
Architecture
A Selenium setup is a remote-control system, and its architecture reflects that. Your test code, written through a language binding, issues WebDriver commands over HTTP to a browser-specific driver — chromedriver, geckodriver, msedgedriver — which in turn controls the real browser. Every click and every query is a round trip. Understanding this is not academic: it explains Selenium’s latency, why network and timing matter so much, and why the whole discipline of explicit waits exists. Design with that grain and the suite is stable; ignore it and you get races.
Above the protocol, the architecture that matters is the one you impose on the test code. We separate three layers deliberately: the tests, which read as plain descriptions of behaviour; the page objects, which own the selectors and interactions for each screen; and the driver and configuration layer, which handles browser setup, waits and grid connection. Keeping these apart is what lets a large suite survive UI change and lets several engineers work in it without collisions. When runs need to scale, Selenium Grid slots in at that lowest layer without the tests above ever needing to know.
Performance
It is honest to say Selenium is not fast. Because every interaction is a real command to a real browser over a protocol, an end-to-end suite is slower than unit or integration tests by orders of magnitude, and slower than some newer E2E tools that run closer to the browser. That is a cost you accept for real-browser fidelity, and the goal is to manage it, not to pretend it away. We keep suites fast enough to be useful by testing the right things at this level and pushing everything else down the testing pyramid to cheaper, faster layers.
The largest practical lever is parallelism. Selenium Grid runs tests concurrently across browsers and machines, so wall-clock time is governed by your slowest single test rather than the sum of all of them — which is what makes running the full suite on every change realistic. Beyond that, performance comes from discipline: well-targeted explicit waits instead of fixed sleeps, independent tests that need no slow shared setup, and stable selectors that do not force expensive retries. We measure suite duration and flake rate as first-class metrics, because a slow or flaky suite that people skip protects nothing.
Security
Automated browser testing touches sensitive material — login credentials, test accounts, and sometimes production-like data — so we treat the suite as part of your attack surface, not a throwaway. Secrets never live in the test code or the repository; they come from the CI system’s secret store or a secure vault at run time, and test accounts are scoped to the least privilege a scenario needs. Where a suite runs against a shared environment, we make sure it cannot mutate data other people depend on.
When Selenium is used for automation or scraping rather than testing, the security and legal picture is different and we are explicit about it: respecting a site’s terms and robots directives, rate-limiting to avoid harming the target, and handling any collected data lawfully. On the infrastructure side, Grid nodes and cloud device farms are execution environments we harden and isolate like any other, and we keep browser and driver versions patched, since an out-of-date driver is as much a liability in a pipeline as anywhere else.
Scalability
Selenium scales along two independent axes, and they need different answers. The first is execution: running more tests, on more browsers, faster. Here Selenium Grid is the mechanism — add nodes, self-hosted or on a cloud provider, and the suite fans out across them. The precondition is that tests are independent and stateless, each setting up and tearing down its own data, so they can run concurrently in any order without interfering. We design for that from the first test, because retrofitting isolation into a suite that assumed serial execution is painful.
The second axis is the one teams underestimate: the suite as a codebase. A Selenium suite grows like any software, and without structure it rots — brittle selectors, duplicated interactions, and flaky tests that accumulate until people stop trusting the results. The Page Object Model, shared and stable locator conventions, and a ruthless attitude to flakiness are what let a suite grow to thousands of tests and stay maintainable. We treat test code with the same engineering standards as production code, because at scale that is exactly what it is.
Selenium integrations & ecosystem
The technologies we most often pair with it — each links to how we work with it.
How we work
We start with a question many shops skip: is Selenium actually the right tool for this suite? For broad cross-browser coverage, a non-JavaScript stack, or an existing investment worth keeping, the answer is often yes. For a new suite on a modern app with a JavaScript-comfortable team, we will usually point you at Playwright or Cypress instead — better auto-waiting, speed and developer experience — because recommending the wrong tool to win the work would cost you more than it costs us to be honest. That conversation happens first, before any code.
When Selenium is the right choice, we build the suite the way it has to be built to stay reliable: explicit waits rather than sleeps, the Page Object Model from the outset, stable selectors agreed with your developers, and independent tests that run in parallel on Grid and in CI. The engineers who write the suite are the ones who keep it green, so we optimise for the six-month reality of a maintained suite, not a demo that passes once. You get test code held to production standards, wired into your pipeline, and a straight account of its speed and its limits.
The service behind it
Delivered throughCloud EngineeringWhat we build with Selenium
The disciplines this technology most often shows up in — from a first build to taking over and stabilising an existing one.
How we deliver
- 01
Discover
We map the system, the constraints and the business it serves — including the parts nobody documented.
Architecture brief
- 02
Architect
Decisions get made, written down and defended before a line of production code exists.
Decision records
- 03
Build
Short cycles against working software. You see progress in the product, not in a status deck.
Shipping increments
- 04
Operate
Monitoring, incident response and iteration. The system is alive, so the engagement is too.
Runbooks & SLOs
Industries we use Selenium in
Domain knowledge changes what gets built. A few of the sectors we know before the first meeting.
Also in Cloud & Infrastructure
Why teams choose us for Selenium
Senior engineers only
Selenium is reliable only when it is engineered with discipline — waits, page objects, stable selectors, isolation. The people building your suite have made those mistakes before and know how to avoid them, so your pipeline is not where they learn what causes flakiness.
We operate what we build
We run the suites we ship in real pipelines, so we optimise for the maintained reality — low flake rate, fast runs, tests people actually trust — rather than a suite that passes once in a demo and rots by the next quarter.
Honest about the tool
We will tell you plainly when Playwright or Cypress would serve you better than Selenium, and when Selenium is genuinely the right call. We would rather point you at the better tool than sell you the familiar one.
Test code held to production standards
We treat a test suite as software, because at scale it is. The same standards we apply to production code — structure, review, no tolerance for flakiness — are what let a suite grow to thousands of tests without collapsing under its own weight.
Typical timeline
- 01
Assessment and tool decision
A few days to a fortnight establishing what needs testing, which browsers genuinely matter, the state of any existing suite, and — honestly — whether Selenium or a newer tool is the right foundation before code is written.
- 02
Framework and first journeys
Two to three weeks standing up the suite structure — waits, page objects, selector conventions, CI integration — and covering the first critical user journeys end to end, so the approach is proven against your real application.
- 03
Coverage build-out
Journey-by-journey expansion in short cycles, each addition running green in the pipeline, with parallelism on Grid introduced as the suite grows enough to need it.
- 04
Stabilisation and handover
Driving flake rate down, tuning run time, documenting the patterns and selectors, and handing over a suite your team can own, extend and trust.
How pricing works
- Fixed-scope builds for a defined suite — a set of critical journeys covered end to end across agreed browsers, integrated into your CI — quoted once we understand the application and its surfaces.
- Monthly senior engagement for ongoing test engineering, where coverage grows with the product and you want continuity rather than a one-off deliverable.
- Focused audits and rescues for an existing Selenium suite — diagnosing flakiness, restructuring to page objects, stabilising selectors and speeding up runs — priced by the assessment.
Hire Selenium engineers
Need Selenium capacity on your own team? We embed named senior engineers into your existing team — reporting to your leads, working in your rituals — so you add capacity without a hiring cycle.
Hire Selenium engineersCommon questions
Should we use Selenium or Playwright or Cypress for a new project?
For a brand-new E2E suite on a modern web app, with a team comfortable in JavaScript or TypeScript, Playwright or Cypress is usually the better choice — they give you auto-waiting, better speed, less flakiness and a stronger developer experience out of the box. Selenium still wins when you need the broadest real-browser coverage, including Safari and older or enterprise browsers, when your team wants to write tests in Java, C# or another non-JavaScript language, or when you already have a substantial suite worth keeping. We give you a straight recommendation for your specific case rather than a blanket rule.
Why are Selenium tests so flaky, and can that be fixed?
Most Selenium flakiness comes from tests acting before the browser is ready — a click or a read that races the page. It is fixable, but only with discipline: explicit waits for the specific state each step depends on instead of fixed sleeps, stable selectors that do not break on cosmetic changes, and independent tests that do not depend on shared state. Flakiness is not an inherent, unavoidable property of Selenium; it is what you get when the suite is written without that engineering. Removing it is much of the work in making a Selenium suite trustworthy.
What is the Page Object Model and do we really need it?
The Page Object Model puts the selectors and interactions for each screen into a single class, so tests call methods like login or addToBasket rather than hunting for elements directly. When the UI changes, you update one page object instead of every test that touched that screen. At any real scale it is not optional — it is the difference between a suite that survives UI change and one that becomes unmaintainable. We build with it from the outset, because retrofitting it into a sprawling suite later is far more expensive.
How do we run Selenium tests across many browsers quickly?
Selenium Grid distributes tests in parallel across multiple browsers and machines, self-hosted or on a cloud device farm, so a suite that would run for an hour in series can finish in minutes. The precondition is that tests are independent and stateless — each setting up and cleaning up its own data — so they can run concurrently in any order. We design suites for that isolation from the start and wire Grid into CI so the full cross-browser run can gate every change rather than run overnight.
Can Selenium be used for scraping and browser automation, not just testing?
Yes. Because Selenium drives a real browser, it can automate any workflow a person could do in one, including pages that only render through JavaScript, and it is a common choice for scraping content that a plain HTTP request cannot reach. It is heavier and slower than a direct HTTP approach, so it is the right tool only when real-browser rendering or interaction is genuinely needed. When we use it this way we are careful about the legal and ethical side — respecting a site’s terms and robots directives, rate-limiting to avoid causing harm, and handling collected data lawfully.
Building on Selenium?
A technical conversation with the engineers who would do the work. If we are not the right fit, we will say so on the call.