Power Your Software Testing with AI Agents and Cloud
The Native AI-Agentic Cloud Platform to Supercharge Quality Engineering. Test Intelligently and Ship Faster.
- TestMu AI (Formerly LambdaTest)
- /
- Blog
- /
- Python Browser Automation: Playwright & Selenium [2026]
Python Browser Automation: Playwright & Selenium [2026]
Pick the right tool, run headless or in the cloud, avoid bot detection, and let an AI agent drive, with runnable Python examples throughout.
Published on:
Python browser automation is the process of writing Python that drives a real browser. The script opens pages, clicks, fills forms, and reads what actually renders, instead of calling an API behind the page.
The first script is never the hard part. Picking the right library, then keeping runs stable once the page changes, is where most of the time goes.
TL;DR
Python browser automation drives a real browser from Python to test, scrape, and automate web tasks. The right choice turns on one question: whether the page needs a real browser at all, and how much scale and stealth you need on top of that.
- Static pages - Requests or httpx fetch HTML directly and run far faster than any browser.
- Full control - Playwright suits new projects; Selenium wins on ecosystem and legacy browser reach.
- Scale - a cloud grid runs hundreds of parallel sessions across browsers you do not maintain.
- AI agents - browser-use drives the page from a plain-English goal when layouts keep shifting.
What Is Python Browser Automation
Python browser automation is driving a real web browser from Python code, using a library such as Selenium or Playwright, so scripts navigate, click, type, and read pages the same way a person would.
The idea is old; what changed is the tooling. Early scripts tied every action to a brittle selector, so a small layout change broke the run.
Modern libraries wait for elements on their own and bundle their own browsers. That removes most of the setup and flakiness that made the old approach painful.
Three jobs cover most use cases:
- Testing - drive the app through real user flows and assert what the page shows.
- Scraping - render JavaScript-heavy pages, then read data the raw HTML does not expose.
- Task automation - repeat logins, downloads, and form submissions no one wants to do by hand.
Which library makes that easy is the next decision.
How to Choose a Python Browser Automation Library
Choose by what the page needs. If the content is static, Requests or httpx are fastest. If it needs a real browser, pick Playwright for new work or Selenium for its ecosystem and legacy reach.
The table below maps each option to the job it fits, so you can pick before writing any code.
| Tool | Best for | Speed | Watch out for |
|---|---|---|---|
| Requests + httpx | Static pages and APIs | Fastest | Cannot run JavaScript |
| Selenium | Legacy browsers, large ecosystem | Moderate | More setup, manual waits |
| Playwright | Most new projects | Fast | Newer, smaller community |
| undetected-chromedriver | Sites that block bots | Moderate | Breaks when vendors update |
| browser-use | AI-driven, shifting layouts | Slow | Costs per run, less predictable |
For a new project, start with Playwright. Drop to Requests when the page is static. Reach for the stealth or AI options only when a site actively blocks you.
How to Automate a Browser With Selenium in Python
To automate a browser with Selenium in Python, install selenium, start a WebDriver, then locate elements and act on them. Add explicit waits so each step runs only after the element renders.
Here is a headless login that waits for the field instead of sleeping for a fixed time:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
options = webdriver.ChromeOptions()
options.add_argument("--headless=new") # run without a visible window
driver = webdriver.Chrome(options=options)
driver.get("https://example.com/login")
# wait for the field instead of a fixed sleep
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.NAME, "username"))
)
driver.find_element(By.NAME, "username").send_keys("qa@test.dev")
driver.find_element(By.NAME, "password").send_keys("secret")
driver.find_element(By.CSS_SELECTOR, "button[type=submit]").click()
print(driver.title) # expected: "Dashboard"
driver.quit()That WebDriverWait call is what separates a stable script from a flaky one; the Selenium with Python guide covers locators and waits in depth.
Note: Prefer to see it running first? Create a free account and point your first Python script at the cloud grid in minutes. Start free with TestMu AI or book a demo.
How to Automate a Browser With Playwright in Python
To automate a browser with Playwright in Python, install playwright, download its browsers, then launch a page and act on it. Playwright auto-waits for elements, so most explicit waits vanish.
The same login in Playwright is shorter, because the waits are built in:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto("https://example.com/login")
# Playwright auto-waits for the element before acting
page.fill("input[name=username]", "qa@test.dev")
page.fill("input[name=password]", "secret")
page.click("button[type=submit]")
page.wait_for_url("**/dashboard")
print(page.title()) # expected: "Dashboard"
browser.close()Notice there are no manual waits before each action. For fixtures, tracing, and parallel runs, the Playwright Python tutorial goes further.
How to Run a Headless Browser in Python
Headless means the browser runs with no visible window. It uses less memory and runs on CI servers that have no display, which is why most production runs are headless.
The flag differs by library:
# Selenium
options.add_argument("--headless=new")
# Playwright
browser = p.chromium.launch(headless=True)Headless is not free: some sites treat it as a bot signal, and a few layouts render differently. When that bites, the Python headless browser guide covers the fixes.
How to Run Python Browser Automation at Scale
One browser on your laptop is fine while you build. A real suite means many browsers at once, across operating systems you do not want to install and maintain.
This is where a cloud grid helps. TestMu AI Automation Cloud runs your Selenium and Playwright scripts across 3,000+ browser and OS combinations in parallel. You change the connection URL, not your code.
What it changes for a Python workflow:
- No infrastructure to run - point a remote WebDriver or WebSocket URL at the grid, and there is nothing to install.
- True parallelism - hundreds of sessions run at once, so a suite finishes in minutes, not hours.
- Real devices, not emulators - run on 10,000+ real iOS and Android devices and desktop browsers.
- Fewer flaky failures - SmartWait and auto-healing absorb the timing and selector breaks that kill long runs.
Running the sessions in parallel is what turns a long sequential suite into a short one.
The same scripts run locally while you build and on the grid when scale demands it, with no rewrite in between.
How to Avoid Bot Detection in Python Browser Automation
To avoid bot detection, cut the signals that mark a script as automated. Use undetected-chromedriver or nodriver, hide the navigator.webdriver flag, set a real user agent, and slow the pace.
undetected-chromedriver patches the most obvious tell for you:
import undetected_chromedriver as uc
driver = uc.Chrome(headless=False)
driver.get("https://example.com")
# the navigator.webdriver flag is patched, so this prints None
print(driver.execute_script("return navigator.webdriver"))
driver.quit()No approach lasts forever, because detection vendors keep updating their fingerprinting. Treat stealth as ongoing maintenance, not a one-time fix.
Can an AI Agent Control the Browser in Python
Yes. browser-use pairs a language model with Playwright, so you describe a goal in natural language and the agent clicks for you. It is slower and less predictable than a hand-written script.
The trade-off is control. A scripted flow does the same thing every run; an agent reasons each time, which helps on brittle pages but is harder to gate in CI.
A minimal browser-use agent looks like this:
import asyncio
from browser_use import Agent
from browser_use.llm import ChatAnthropic
async def main():
agent = Agent(
task="open the demo store, search for a blue shirt, add it to the cart",
llm=ChatAnthropic(model="claude-sonnet-4-6"),
)
await agent.run()
asyncio.run(main())The exact API shifts release to release, so check the browser-use project before you build on it.
browser-use keeps the agent inside your Python process. To run that agentic flow as a command and gate CI on it, TestMu AI Kane CLI drives real Chrome from the terminal.
You give it a goal in natural language, not selectors. It proves the flow reached the state you described, then hands back a pass or fail with evidence you can replay.
Installing it is a single npm command, and the Kane CLI documentation covers the modes, exit codes, and CI setup.
What makes it fit an agent workflow:
- Natural-language objectives - describe the flow in words; there are no selectors to write or maintain.
- Real Chrome - it drives the browser over the DevTools Protocol and only does what a user could.
- Deterministic verdict - it passes only when the page reaches the state you described.
- CI-ready exit codes - 0 passes and 1 fails, so a pipeline can branch on the result.
It runs headless in Agent Mode and streams a structured NDJSON result your pipeline can read as the flow executes.
How to Keep Python Browser Automation Reliable
Most automation fails for the same few reasons. These habits head off the common ones:
- Wait on state, not time - replace fixed sleeps with waits on the element or network.
- Pin selectors to intent - prefer roles, labels, and test IDs over brittle CSS paths.
- Run headless in CI - match local and pipeline behavior by testing headless from the start.
- Isolate sessions - a fresh browser context per test stops cookies leaking between runs.
- Retry only safe steps - a blind retry on a submit can double-charge or double-post.
- Assert the outcome - a click that lands on nothing still counts as done without a check.
None of this is specific to one library. Get the waits and assertions right and most flakiness disappears, whichever tool you picked.
Conclusion
Python browser automation comes down to two choices. Pick the tool that matches the page, then decide where it runs.
Start with Playwright for most new work, keep Requests for static pages, and add stealth or an AI agent only when a site forces the issue.
Then take one real flow, make it headless, and run it in parallel on a grid. That single step turns a fragile script into automation you can trust on every build.
Author
Salman is a Test Automation Evangelist and Community Contributor at TestMu AI, with over 6 years of hands-on experience in software testing and automation. He has completed his Master of Technology in Computer Science and Engineering, demonstrating strong technical expertise in software development, testing, AI agents and LLMs. He is certified in KaneAI, Automation Testing, Selenium, Cypress, Playwright, and Appium, with deep experience in CI/CD pipelines, cross-browser testing, AI in testing, and mobile automation. Salman works closely with engineering teams to convert complex testing concepts into actionable, developer-first content. Salman has authored 120+ technical tutorials, guides, and documentation on test automation, web development, and related domains, making him a strong voice in the QA and testing community.
Reviewer
Navin Chandra is a Member of Technical Staff at TestMu AI (formerly LambdaTest), building the open-source automation that powers its Selenium and Appium cloud grid. A committer to both Selenium and Appium, he implemented WebDriver BiDi support in Selenium for real-time browser events and bidirectional control and is developing Apple's iOS RemoteXPC protocol in Appium to enable low-level wireless communication with iOS system services. He contributes to Selenium across multiple language bindings as a member of the Selenium GitHub organization. He has served as a Google Summer of Code mentee and mentor at openSUSE and an LFX mentee at CNCF's KubeArmor, and is a SUSE Certified Deployment Specialist. Navin holds a B.Tech in Computer Science.
Python Browser Automation FAQs
Did you find this page helpful?
More Related Blogs
TestMu AI forEnterprise
Get access to solutions built on Enterprise
grade security, privacy, & compliance
- Advanced access controls
- Advanced data retention rules
- Advanced Local Testing
- Premium Support options
- Early access to beta features
- Private Slack Channel
- Unlimited Manual Accessibility DevTools Tests






