Keep the Selenium tests, page objects, and reporting stack you trust. Swap the grid underneath with Steel sessions that start in under a second, run from minutes to hours (up to 24 hours on Enterprise), and record every run so failures come with evidence. You still call webdriver.Remote; Steel just hosts the browser, manages lifecycle, and gives you replay URLs tied to each sessionId.
Steel is not trying to replace WebDriver. It supplies the managed browser runtime when your language mix or compliance rules mean Selenium is staying put. That means a custom connection class for Steel headers, explicit session creation with is_selenium: true, and predictable release calls once the driver quits.
What stays the same
selenium.webdriverAPI surface, from capabilities to waits.- Test harnesses: pytest, JUnit, NUnit, or bespoke runners.
- Page objects, selectors, and assertion utilities.
- CI wiring: you still export
STEEL_API_KEY, set env specific URLs, and fan out suites the same way. - Local debugging: you can run against Chrome on your laptop until you point the job at Steel.
What Steel adds
| Job | DIY grid or localhost | Selenium on Steel |
|---|---|---|
| Startup | Wait for EC2 or an on-prem VM to warm Chrome | Steel Cloud sessions start in under a second on average — ~0.18s for session creation, ~0.89s end-to-end per Steel's own benchmark — and hand you a ready endpoint |
| Session length | Browsers restart frequently to keep hosts clean | Steel sessions run up to your plan ceiling (15 min Launch · 1 hr Scale · up to 24 hr Enterprise); set timeout explicitly for long flows |
| Evidence | Console logs and screenshots if you wired them yourself | Each sessionId maps to logs plus replay exports so failures are reviewable and shareable |
| Anti-bot | Patchy proxy rotation and brittle stealth flags | Steel Cloud supplies managed proxies, fingerprints, and CAPTCHA solving — set on the is_selenium session just like Playwright/Puppeteer |
| Scale & ops | Maintain Selenium Grid, Docker images, shared storage | Steel handles fleet health; you just connect and release |
Minimal integration path
- Install the SDK (
pip install steel-sdk selenium) so you can create and release sessions explicitly. - Create a session for Selenium:
session = client.sessions.(is_selenium=True, persist_profile=True, timeout=3600000) - Wrap Selenium’s RemoteConnection to add Steel headers:
steel-api-key: proves you can attach to the sessionsession-id: routes the WebDriver calls to the browser Steel already provisioned
- Connect your existing test with
webdriver.Remote(command_executor=CustomRemoteConnection(...), options=webdriver.ChromeOptions()). - Release sessions on exit using
client.sessions.release(session.id)orclient.sessions.release_all()in afinallyblock so concurrency slots free up fast.
Example code (Python)
import os
from selenium import webdriver
from selenium.webdriver.remote.remote_connection import RemoteConnection
from steel import Steel
STEEL_WS = "http://connect.steelbrowser.com/selenium"
client =(steel_api_key=.["STEEL_API_KEY"])
class SteelRemote(RemoteConnection):
def __init__(self, url: str, session_id: str):
super().__init__()
self._session_id = session_id
def get_remote_connection_headers(self, parsed_url, keep_alive=False):
headers = super().(,)
headers.({
"steel-api-key":.["STEEL_API_KEY"],
"session-id": self.,
})
return headers
def run(url: str):
session = client.sessions.(is_selenium=True, persist_profile=True)
driver = webdriver.(
command_executor=(,.),
options=.(),
)
try:
driver.()
# ... your assertions ...
finally:
driver.()
client.sessions.(.)
details = client.sessions.(.)
print("Replay:",.)
if __name__ == "__main__":
("https://news.ycombinator.com")Where Steel fits vs Selenium Grid
| Scenario | Keep Selenium Grid | Move to Steel |
|---|---|---|
| Language coverage across Python, Java, C#, Ruby | Already works locally; no managed runtime needed | Same story, just point WebDriver at Steel and stop tending grid nodes |
| Long authenticated flows that time out mid run | Sessions restart unless you hand roll persistence | Steel sessions run up to your plan ceiling (15 min Launch · 1 hr Scale · up to 24 hr Enterprise) and can persist profiles up to 300 MB |
| Compliance and audit pressure | Evidence depends on homegrown logging | Steel records every run and keeps replay URLs plus Agent Traces per session |
| Anti-bot escalation | DIY scripts juggling proxies and CAPTCHA plugins | Steel handles proxies (use_proxy), CAPTCHA solving (solve_captcha), and stealth (stealth_config) on the is_selenium session itself, no extra Selenium-side plugins |
| Burst scaling for nightly suites | Add more servers or wait in queue | Reserve higher Steel Cloud tiers — up to 100 concurrent sessions on Scale, 1,000+ on Enterprise |
Trade-offs and guardrails
- Steel's Selenium integration supports the same session-level capabilities as Playwright and Puppeteer. Proxies (
use_proxy), CAPTCHA solving (solve_captcha), and stealth (stealth_config) are configured when you create the session withsessions.create(is_selenium=True), so the Selenium driver doesn't need to know about them. The genuine Selenium-specific trade-off is protocol and latency: Selenium speaks the W3C WebDriver protocol over HTTP rather than CDP, so each command is an HTTP round-trip — preferWebDriverWaitovertime.sleep. - Max session time is tiered — see Pricing/Limits (15 min Launch · 1 hr Scale · up to 24 hr Enterprise; default 5 min) — so set
timeoutexplicitly at session creation for long flows. - You must add the header wrapper because Selenium does not expose a direct way to inject Steel’s auth headers. Without it, Steel drops the connection.
- Sessions idle out if you forget to release them. Treat release calls as mandatory so you do not hit plan caps.
- Profiles support up to 300 MB and expire after 30 idle days. For heavy Selenium flows, trim downloads or export files through the Files API before quitting.
- Steel Local is fine for laptops or small CI agents when you want to keep everything on-prem, but note that Credentials API, Files API, CAPTCHA solving, and the dedicated Stealth Browser are Steel Cloud-only, and Steel Local is capped at concurrency 1. Use Steel Cloud once you need managed proxies, enterprise security (SSO and HIPAA-ready BAA), or high concurrency.
Works for / not yet
- Works when your org has thousands of Selenium specs and no appetite for a framework rewrite, but you still want reliable cloud browsers.
- Works when you need Python or Java bindings side by side with TypeScript-based agents because everything connects over the same Sessions API.
- Not yet ideal when you need the absolute lowest per-command latency; Selenium’s HTTP-based WebDriver protocol adds a round-trip per action versus CDP-native clients, so latency-sensitive agents may prefer Playwright or Puppeteer.
Next steps
- Drop the
SteelRemotehelper into your Selenium utilities module and point one suite at Steel Cloud. - Tag every session you create with your existing run or build ID so logs, replays, and approvals line up.
- Capture the limitations above in your test README so the team knows which flows can move today and which are bounded by tier limits or Selenium's HTTP-round-trip latency.
Humans use Chrome. Agents use Steel.