nodriver
Skill75 starsChanged 4 months agoMITView on GitHub
Write Python browser automation scripts using nodriver (undetected Chrome DevTools Protocol). Use when: writing web scrapers, automating logins, filling forms, bypassing anti-bot systems (Cloudflare, Captcha), taking screenshots, managing cookies, or any browser automation that needs to avoid detection. Triggers on: nodriver, undetected browser, web scraping, browser automation, bypass captcha, bypass cloudflare, headless chrome, CDP automation.
In this repository59 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- skills/heygen-skills/CLAUDE.mdCLAUDE.md
- 1passwordSkill
- ask-curlSkill
- boardSkill
- cleanup-unused-filesSkill
- codeflow-maintainerSkill
- codex-session-managerSkill
- coven-astraSkill
- coven-board-entrySkill
- coven-charmSkill
- coven-cloud-maintainerSkill
- coven-codySkill
- coven-echoSkill
- coven-identity-canonSkill
- coven-kittySkill
- coven-parallel-workSkill
- coven-sageSkill
- coven-task-managerSkill
- daily-dev-agenticSkill
- discrawlSkill
- disk-space-optimizerSkill
- epubSkill
- familiar-board-stewardshipSkill
- heygen-avatarSkill
- heygen-videoSkill
- heygen-skillsSkill
- higgsfield-generateSkill
- higgsfieldSkill
- linear-issue-managementSkill
- lit-ui-designerSkill
- lobsterSkill
- maintainer-barSkill
- memory-recallSkill
- memory-timeline-managerSkill
- ml-engineerSkill
- ocrSkill
- openclaw-devSkill
- openclaw-trustSkill
- opencoven-designSkill
- OpenCoven Role Creation ProcessSkill
- pr-agentSkill
- project-managerSkill
- prompt-engineerSkill
- prompt-vaultSkill
- research-ingestionSkill
- ritual-dapp-frontendSkill
- rollcallSkill
- security-agentSkill
- skill-scannerSkill
- slidev-deck-pipelineSkill
- tauri-apple-releaseSkill
- threejs-animationSkill
- tinyfish-agent-runSkill
- tinyfish-browserSkill
- tinyfish-fetchSkill
- tinyfish-searchSkill
- tinyfishSkill
The file
Files
nodriver
Async Python library for undetected browser automation via CDP. Successor to undetected-chromedriver. No Selenium, no chromedriver binary.
Docs: https://ultrafunkamsterdam.github.io/nodriver
Prerequisites
- Chrome/Chromium/Edge/Brave installed (default location)
- Headless environments: use Xvfb or
headless=True
Quick start
import nodriver as uc
async def main():
browser = await uc.start()
tab = await browser.get('https://example.com')
if __name__ == '__main__':
uc.loop().run_until_complete(main())Critical quirks (non-obvious)
- Never use
asyncio.run()— useuc.loop().run_until_complete(main()). await tabbetween rapid interactions — syncs DOM state, prevents stale refs. Insert whenever elements aren't found or interactions fail.- Fresh profile each run by default — set
user_data_dir="/path"to persist. find(text, best_match=True)is expensive but accurate (matches by text length). Useselect(css)when selector is known.- All lookup methods retry until
timeout(default 10s) — double as wait conditions.await tab.select('body')= wait for page load. expert=Trueincreases detectability — opens shadow roots and disables web security, but WAFs detect it more easily.verify_cf()requiresopencv-python— English only, doesn't work in expert mode.
Start options
browser = await uc.start(
headless=False,
user_data_dir="/path/to/profile",
browser_executable_path="/path/to/bin",
browser_args=['--proxy-server=socks5://user:pass@host:port'],
lang="en-US",
)Or use Config() for the same options. Per-context proxies: browser.create_context(proxy_server="socks5://...").
Element lookup
btn = await tab.find("Sign in", best_match=True) # by text (smart match)
email = await tab.select("input[type=email]") # by CSS selector
items = await tab.select_all("a[href]") # all matching CSS
node = await tab.xpath("//div[@class='x']//p[1]") # by XPath
all_btns = await tab.find_all("Add to cart") # all matching textCookies (persist logins)
await browser.cookies.save('session.dat')
await browser.cookies.load('session.dat')Event handlers + custom CDP
import nodriver.cdp as cdp
tab.add_handler(cdp.network.RequestWillBeSent, lambda e: print(e.request.url))
await tab.send(cdp.emulation.set_device_metrics_override(width=375, height=812, device_scale_factor=3, mobile=True))Anti-bot
await tab.verify_cf() # Cloudflare checkbox (needs opencv-python)
await tab.template_location('template.png') # custom image match in viewportFull API reference
For complete method signatures (Browser, Tab, Element, Config, CDP): references/api.md
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

