🛡️ GDNox
Undetectable Browser Automation Library
Stealth browser automation with closed Shadow DOM access and antibot bypass capabilities
Features • Installation • Quick Start • Stealth Patches • Bypassed Antibots • API • 📚 Documentation
✨ Features
| Feature | Description |
|---|---|
| 🔌 Direct CDP | Pure Chrome DevTools Protocol - no WebDriver detection |
| 👻 Shadow DOM Access | Pierce closed Shadow Roots (impossible with Selenium/Playwright) |
| 🧠 Human Behavior | Bezier curve mouse movements, realistic typing delays |
| 🎭 Fingerprint Spoofing | Canvas, WebGL, AudioContext randomization |
| 📜 History Seeding | Pre-populate browsing history and cookies |
| 🌐 Proxy Support | Full proxy support with authentication |
| ⚡ Async First | Built on asyncio for high performance |
| 🔄 Auto OOP Iframe Handling | Automatically attach to cross-origin iframes |
📦 Installation
pip install gdnox
Or with Poetry:
poetry add gdnox
Requirements
- Python 3.10+
- Google Chrome or Chromium installed
🚀 Quick Start
import asyncio
from GDNox import Browser
async def main():
async with Browser() as browser:
tab = await browser.new_tab()
await tab.goto("https://example.com")
# Find elements - automatically pierces Shadow DOM!
element = await tab.find("h1")
print(await element.text())
# Human-like click
button = await tab.find("button")
await button.click() # Uses realistic mouse movement
# Take screenshot
await tab.screenshot("screenshot.png")
asyncio.run(main())
Clicking Cloudflare Turnstile
import asyncio
from GDNox import Browser
async def solve_turnstile():
async with Browser() as browser:
tab = await browser.new_tab()
await tab.goto("https://example.com/protected-page")
# Wait for iframe to load
await tab.sleep(3)
# GDNox automatically finds elements inside cross-origin iframes!
checkbox = await tab.find("input[type='checkbox']")
if checkbox:
await checkbox.click()
print("✅ Clicked Turnstile checkbox!")
asyncio.run(solve_turnstile())
🛡️ Stealth Patches
GDNox applies multiple patches to avoid bot detection:
Navigator Patches
| Patch | Description |
|---|---|
navigator.webdriver |
Removed/undefined (not false) |
navigator.plugins |
Spoofed with realistic Chrome plugins |
navigator.languages |
Configurable language array |
navigator.permissions |
Patched query() for notifications |
Browser Object Patches
| Patch | Description |
|---|---|
window.chrome |
Complete Chrome runtime object simulation |
chrome.runtime |
Mocked connect() and sendMessage() |
chrome.csi |
Mocked timing function |
chrome.loadTimes |
Mocked page timing function |
Fingerprint Randomization
| Patch | Description |
|---|---|
| Canvas | Noise injection on getImageData() and toDataURL() |
| WebGL | Spoofed UNMASKED_VENDOR_WEBGL and UNMASKED_RENDERER_WEBGL |
| WebGL2 | Same patches for WebGL2 context |
| Plugins Array | Realistic PDF plugins when empty |
Profile Seeding
| Feature | Description |
|---|---|
| Browser History | Pre-populated with ~40 popular sites (US + BR) |
| Cookies | Realistic tracking cookies for major sites |
| Local Storage | Pre-seeded storage for common sites |
Runtime Evasion
| Technique | Description |
|---|---|
| Isolated Worlds | JavaScript execution in isolated contexts |
| No Runtime.enable | Avoids detectable CDP domain activation |
| No Console.enable | Prevents console leak detection |
🎯 Bypassed Antibots
GDNox has been tested against the following antibot solutions:
| Antibot | Status | Notes |
|---|---|---|
| Cloudflare Turnstile | ✅ Bypassed | Full shadow DOM + iframe support |
| Cloudflare Challenge | ✅ Bypassed | Stealth patches pass checks |
| DataDome | ✅ Bypassed | Fingerprint randomization works |
| PerimeterX (HUMAN) | ✅ Bypassed | Human behavior simulation |
| Akamai Bot Manager | ✅ Bypassed | Sensor data passes validation |
| Kasada | ⚠️ Partial | May require additional configuration |
| Shape Security | ⚠️ Partial | Depends on site implementation |
| reCAPTCHA v2 | ⚠️ Detection only | Checkbox can be clicked, solving needs additional service |
| hCaptcha | ⚠️ Detection only | Same as reCAPTCHA |
Shadow Root Access
GDNox can access closed Shadow DOMs - something impossible with standard automation tools:
# This works even inside closed shadow roots!
checkbox = await tab.find("input[type='checkbox']")
How it works:
- Uses
DOM.getDocumentwithpierce: true - Automatically traverses all shadow roots
- Resolves elements via
DOM.resolveNodewithbackendNodeId
📖 API Reference
Browser
Browser(
chrome_path=None, # Path to Chrome (auto-detected)
headless=False, # Headless mode (not recommended for stealth)
user_data_dir=None, # Profile directory
proxy=None, # Proxy URL (http://user:pass@host:port)
extra_args=[], # Additional Chrome arguments
auto_seed=True, # Auto-seed history/cookies
)
Tab
await tab.goto(url, wait_until="load", timeout=30.0)
await tab.find(selector, timeout=5.0)
await tab.find_all(selector)
await tab.wait_for_selector(selector, visible=False, timeout=30.0)
await tab.wait_for_function(expression, timeout=30.0)
await tab.race(selectors=[], js_functions=[], timeout=30.0)
await tab.evaluate(expression)
await tab.screenshot(path)
await tab.content()
await tab.sleep(seconds)
Element
await element.click(human_like=True)
await element.type(text, human_like=True)
await element.text()
await element.inner_html()
await element.get_attribute(name)
await element.set_attribute(name, value)
await element.is_visible()
await element.scroll_into_view()
await element.focus()
Network Interception
network = tab.network
@network.on('request')
async def on_request(request):
print(f"Request: {request.url}")
@network.on('response')
async def on_response(response):
body = await response.body()
print(f"Response: {len(body)} bytes")
@network.intercept('*api.example.com*')
async def intercept_api(request):
if '/blocked' in request.url:
await request.abort()
else:
await request.continue_()
🔧 Advanced Usage
Custom Fingerprint
from GDNox import Browser
from GDNox.stealth import FingerprintSpoofer
async with Browser() as browser:
tab = await browser.new_tab()
# Custom WebGL fingerprint
spoofer = FingerprintSpoofer(
tab._cdp,
noise_level=5,
language="en-US",
webgl_config=("Intel Inc.", "Intel Iris OpenGL Engine"),
)
await spoofer.apply(tab._frame_id)
Human-like Mouse
from GDNox.behavior import HumanMouse
mouse = HumanMouse(tab._cdp)
# Bezier curve movement
await mouse.move_to(500, 300, duration=0.8)
# Natural click
await mouse.click()
# Realistic scroll
await mouse.scroll(delta_y=500)
Profile Management
from GDNox.stealth import ProfileManager
# Create persistent profile with pre-seeded data
profile = ProfileManager("/path/to/profile")
profile.seed_history()
profile.seed_cookies()
# Use with browser
async with Browser(user_data_dir="/path/to/profile", auto_seed=False) as browser:
...
📄 License
PolyForm Noncommercial 1.0.0 - Free for personal and non-commercial use only.
See LICENSE for details. For commercial licensing, contact: rafaeldecarvalho.ps@gmail.com
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Made with ❤️ for the automation community
Metadata
Release files for gdnox 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| gdnox-0.1.1.tar.gz | 83.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gdnox-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 127.6 kB
Release files / gdnox-0.1.1.tar.gz
| Download URL | gdnox-0.1.1.tar.gz |
|---|---|
| Size | 83.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0a0fa439f76ea99e8e4ab9723d37c9a21edc6228b0e1047d295954bd98a1c35f
|
|
BLAKE2b-256 checksum How to use checksums |
65855e8245fda90dc8b762fd76b437a4ede1279f353b643ee792593d03b58fd1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.8.3 CPython/3.10.12 Linux/6.6.87.2-microsoft-standard-WSL2
|
Release files / gdnox-0.1.1-py3-none-any.whl
| Download URL | gdnox-0.1.1-py3-none-any.whl |
|---|---|
| Size | 44.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dfd83c22ad3a2aa66bd8802631b9bb7dac8b1f7042d64393d6ea30de011354d2
|
|
BLAKE2b-256 checksum How to use checksums |
d0b48162d1a6d80be85752b218d70b98c30ad6c1749477a81a42c4b2137cee3a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.8.3 CPython/3.10.12 Linux/6.6.87.2-microsoft-standard-WSL2
|