Termux Browser Pilot
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Termux Browser Pilotgoto https://news.ycombinator.com and get the page title"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Termux Browser Pilot v0.17.1
Real browser automation for Termux/Android. No root required.
Firefox (default) or Chromium on Xvfb — runs entirely on your phone. Firefox passes Cloudflare natively via TLS fingerprint. Chromium uses CDP stealth. Both use real device hardware info.
Features
Persistent daemon — browser stays running, sub-second commands
Passes Cloudflare — Firefox: instant TLS-based pass; Chromium: Turnstile handler
No automation framework — Firefox controlled via xdotool + clipboard JS execution
AI-friendly —
--jsonflag on all commands for structured outputReal device fingerprint — auto-detects screen, GPU, CPU, arch, model
Human-like input — Bezier curve mouse, realistic typing, clipboard paste
Session persistence — auto-save/load cookies across restarts
Cookie management — get/set/save/load, Netscape format import/export
Network tracking — capture all request URLs, types, sizes (Chromium only)
Screenshots — viewport or full page PNG, PDF export
Accessibility tree — ARIA roles and names
Cross-device — auto-adapts to any Android device's real specs
Smart element targeting — find clickable elements by visible text
Idle timeout — auto-shutdown daemon after configurable inactivity
Tab management — open, close, switch between browser tabs
Proxy support — HTTP/SOCKS5 proxy for Firefox and Chromium
Request interception — block URLs/domains via JS fetch/XHR hooks
Multi-step macros — chain commands into reusable JSON scripts
Console log capture — capture console.log/warn/error/info output
Download management — auto-download files to ~/.tbp/downloads/
Network request log — capture URLs, types, durations, sizes
DOM mutation observer — watch for element changes in real-time
Element screenshot — capture specific elements by CSS selector
Drag and drop — smooth mouse drag between elements or by offset
Iframe support — list, eval, text, click inside same-origin iframes
File upload — set files on input[type=file] via JS DataTransfer
Geolocation spoofing — override navigator.geolocation coordinates
User agent switching — optional override (default: real browser UA)
Cookie injection — set cookies with domain, path, secure, SameSite
Local/session storage — get, set, remove, clear, list items
Clipboard access — read/write Xvfb system clipboard
Form auto-fill — fill all form fields from JSON spec
Lightweight — no Puppeteer/Playwright dependency
Related MCP server: qutebrowser-mcp
Quick Start
Install
bash setup.sh
# Or manually:
pkg install tur-repo x11-repo
pkg install firefox xorg-server-xvfb xdotool xclip openbox python3
pip install websockets # only needed for Chromium modeCLI (Daemon Mode — Recommended)
Browser starts once, stays running. Commands are instant.
# Navigate (auto-starts daemon on first command)
tbp goto https://example.com
tbp goto https://audiogames.net -cf # Cloudflare bypass
# Read content
tbp text # Page text
tbp links # All links
tbp eval "document.title" # Run JavaScript
tbp a11y # Accessibility tree
# Interact
tbp click "button.submit" # Click element
tbp type "input[name=q]" "hello" # Type into field
tbp press Enter # Press key
tbp scroll --down # Scroll page
tbp find "Sign In" # Find elements by text
tbp find "Submit" --role button # Filter by role
# Tab management
tbp tab new # Open new tab
tbp tab new https://example.com # New tab with URL
tbp tab close # Close current tab
tbp tab next # Next tab
tbp tab prev # Previous tab
tbp tab goto 2 # Switch to tab 2
# Block requests
tbp block ads.example.com tracker.js # Block URL patterns
tbp blocklist # List blocked patterns
tbp unblock ads.example.com # Unblock pattern
# Macros (JSON scripts)
tbp macro workflow.json # Run multi-step macro
# Console log capture
tbp console start # Start capturing logs
tbp console stop # Stop capturing logs
tbp console logs # Show captured logs
tbp console logs --clear # Show and clear buffer
tbp console clear # Clear log buffer
# Downloads
tbp downloads # List downloaded files
# Network request log
tbp network start # Start logging requests
tbp network stop # Stop logging requests
tbp network logs # Show captured requests
tbp network logs --clear # Show and clear
tbp network clear # Clear request log
# DOM mutation observer
tbp observe start # Start watching mutations
tbp observe stop # Stop watching mutations
tbp observe logs # Show captured mutations
tbp observe clear # Clear mutations
# Element screenshot
tbp screenshot-element "div.hero" # Screenshot specific element
tbp screenshot-element "#logo" logo.png
# Drag and drop
tbp drag ".item" --target ".dropzone" # Drag to element
tbp drag ".slider" --dx 100 # Drag by offset
# Iframe support
tbp iframe list # List all iframes
tbp iframe eval "iframe#f1" "document.title" # JS in iframe
tbp iframe text "iframe#f1" # Get iframe text
tbp iframe click "iframe#f1" "button" # Click in iframe
# File upload
tbp upload "input[type=file]" photo.jpg # Upload file (max 5MB)
# Geolocation spoofing
tbp geo set 40.7128 -74.0060 # Set to New York
tbp geo set 51.5074 -0.1278 -a 50 # London, 50m accuracy
tbp geo clear # Clear override
# User agent switching (default: real browser UA — override is optional)
tbp useragent set "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
tbp ua clear # Restore real UA
# Note: Overrides JS-side navigator.userAgent only.
# HTTP User-Agent header stays real (requires restart to change).
# Cookie injection
tbp cookie-set session_id abc123 # Simple cookie
tbp cs token xyz --domain .example.com # With domain
tbp cs pref dark --max-age 86400 --secure # Secure + 1 day
# Local/session storage
tbp storage list # List localStorage
tbp storage get mykey # Get value
tbp storage set mykey myvalue # Set value
tbp storage remove mykey # Remove key
tbp storage clear # Clear all
tbp storage list --type session # sessionStorage
# Clipboard
tbp clipboard read # Read clipboard
tbp clip write "Hello world" # Write to clipboard
# Form auto-fill (JSON file: [{selector, value}, ...])
tbp form-fill form_data.json # Fill all fields
# Proxy support (on start)
tbp start --proxy socks5://127.0.0.1:1080
# Screenshots
tbp screenshot page.png
tbp screenshot page.png --full # Full page
# AI-friendly JSON output
tbp goto https://example.com --json
tbp text --json
tbp links --json
# Session management
tbp status # Daemon status
tbp cookies --save session.json # Save cookies
tbp cookies --load session.json # Load cookies
tbp stop # Graceful shutdownPython API
import asyncio
from src.pilot import Pilot
async def main():
# Firefox (default) — passes Cloudflare natively
async with Pilot() as p:
await p.goto_cf("https://audiogames.net")
print(await p.title())
await p.screenshot("page.png")
# Chromium mode with session persistence
async with Pilot(browser="chromium", session_file="session.json") as p:
await p.goto("https://example.com")
await p.type("input[name=q]", "hello")
asyncio.run(main())Daemon Client (Python)
from src.client import send_command
import asyncio
async def main():
# Auto-starts daemon if not running
r = await send_command("goto", {"url": "https://example.com"})
print(r["data"]["title"])
r = await send_command("text")
print(r["data"]["text"])
r = await send_command("screenshot", {"path": "shot.png"})
asyncio.run(main())MCP Server (for Claude Code / AI Agents)
# Register with Claude Code
claude mcp add tbp -- tbp-mcp
# Or use .mcp.json (already included in repo)
# Tools: browser_goto, browser_text, browser_click, browser_type,
# browser_screenshot, browser_a11y, browser_links, browser_eval,
# browser_scroll, browser_hover, browser_press, browser_find,
# browser_tab_*, browser_block, browser_unblock, browser_blocklist,
# browser_macro, browser_wait, browser_wait_for, browser_cookies_*,
# browser_console_*, browser_downloads, browser_network_*,
# browser_observe_*, browser_mutations*, browser_screenshot_element,
# browser_drag, browser_iframe_*, browser_upload, browser_geo_*,
# browser_useragent_*, browser_cookie_set, browser_storage_*,
# browser_clipboard_*, browser_form_fill, browser_statusRequires: pip install "mcp[cli]>=1.0" (or pip install termux-browser-pilot[mcp]).
Feature Reference
Navigation & Content
Command | Description |
| Navigate to URL. |
| History navigation |
| Get visible page text |
| Get page HTML |
| List all links |
| Execute JavaScript |
| Get page title/URL |
| Find interactive elements by visible text |
| Accessibility tree (ARIA roles and names) |
Interaction
Command | Description |
| Click element. |
| Type text into input |
| Press keyboard key (Enter, Tab, Escape...) |
| Scroll page |
| Hover over element |
| Drag element |
Tab Management
Command | Description |
| Open new tab |
| Close current tab |
| Switch tabs |
| Switch to tab 1-9 |
Screenshots & Export
Command | Description |
| Screenshot (viewport or full page) |
| Screenshot specific element |
| Export page as PDF |
Request Blocking
Command | Description |
| Block URL patterns (domains/substrings) |
| Remove blocked patterns |
| List current blocked patterns |
Console Log Capture
Command | Description |
| Start capturing console.log/warn/error/info |
| Stop capturing (disables re-injection) |
| Show captured logs |
| Clear log buffer |
Network Request Log
Uses PerformanceObserver (passive, no conflict with URL blocker).
Command | Description |
| Start logging network requests |
| Stop logging |
| Show requests (URL, type, duration, size) |
| Clear request log |
DOM Mutation Observer
Command | Description |
| Start watching DOM mutations |
| Stop watching |
| Show mutations (childList, attributes, etc.) |
| Clear mutation buffer |
Iframe Support
Works with same-origin iframes only. Cross-origin iframes are listed but inaccessible.
Command | Description |
| List all iframes (index, src, accessibility) |
| Execute JS inside iframe |
| Get text from iframe |
| Click element inside iframe |
File Upload
Sets files on <input type="file"> elements via JS DataTransfer API. Max 5MB.
Command | Description |
| Upload file to file input |
Geolocation Spoofing
Overrides navigator.geolocation.getCurrentPosition and watchPosition.
Re-injected automatically after page navigation. Saves/restores originals on clear.
Command | Description |
| Set geolocation (accuracy default: 100m) |
| Restore real geolocation behavior |
User Agent Switching
Default: real browser user agent. Override is optional and JS-side only
(navigator.userAgent). HTTP User-Agent header sent to servers stays real.
Re-injected after navigation. Restored on clear.
Command | Description |
| Override navigator.userAgent |
| Restore real user agent |
Cookie Injection
Sets cookies via document.cookie. Cannot set HttpOnly cookies (browser security).
Values are URL-encoded automatically. Name must not contain =, ;, or newlines.
Command | Description |
| Set cookie |
Options: |
Local/Session Storage
Command | Description |
| List all items |
| Get value by key |
| Set key-value pair |
| Remove key |
| Clear all items |
Clipboard Access
Reads/writes the Xvfb virtual display clipboard (not the phone clipboard). Useful for reading after a page copy, or setting before a Ctrl+V paste.
Command | Description |
| Read clipboard text |
| Write text to clipboard |
Form Auto-fill
Fills multiple fields from a JSON file. Handles text inputs, selects,
checkboxes, and radios. Dispatches input + change events (React/Vue compatible).
[
{"selector": "#name", "value": "John Doe"},
{"selector": "#email", "value": "john@example.com"},
{"selector": "select#country", "value": "US"},
{"selector": "#agree", "value": true}
]Command | Description |
| Fill fields from JSON file (max 100) |
CSS Injection
Inject, remove, and list custom stylesheets. Persists across scrolling and re-injects after navigation.
Command | Description |
| Inject CSS (text or file path) |
| Remove stylesheet (or all) |
| List injected stylesheets |
Example: tbp css inject "body{background:#111;color:#eee}" --id darkmode
Wait+Action
Wait for an element to appear in the DOM, then automatically perform an action. Uses MutationObserver for efficient detection.
Command | Description |
| Wait then click (default) |
| Wait then type |
| Wait then get text |
Timeout: Default 10s, max 120s. Uses --timeout flag.
Page Event Capture
Capture DOM events (click, submit, input, change, keydown) with target element info. Re-injects after navigation automatically.
Command | Description |
| Start capturing events |
| Stop and remove listeners |
| Show captured events |
| Clear event log |
Viewport/Window Resize
Control browser window dimensions for responsive testing.
Command | Description |
| Resize window |
| Get current dimensions |
Returns both window size (xdotool) and inner viewport (JS). Range: 100-7680 x 100-4320.
Page Search
Find text on the page with visual highlighting. Navigate between matches.
Command | Description |
| Find and highlight all matches |
| Go to next match |
| Go to previous match |
| Clear highlights |
Highlights persist across scrolling. Current match shown in orange, others in yellow. Re-injects after navigation if search is active.
Shadow DOM Access
Query, read, and click elements inside shadow DOM boundaries. Recursively traverses all shadow roots to find elements.
Command | Description |
| Find element (returns tag, id, text, attributes) |
| Get text content from shadow element |
| Click element inside shadow root |
Response Body Capture
Capture fetch/XHR response bodies for API inspection and debugging. Bodies truncated to 10KB per response, max 500 entries.
Command | Description |
| Start capturing response bodies |
| Stop capturing |
| Show captured responses |
| Clear response log |
Multi-tab Session Management
Save and restore all open browser tabs as named sessions.
Sessions stored in ~/.tbp/sessions/{name}.json.
Command | Description |
| Save all open tabs |
| Restore tabs from session |
| List saved sessions |
| Delete a session |
Note: Tab detection uses Ctrl+1-9 shortcuts (max 9 tabs).
HTTP Header Injection
Inject custom headers into all fetch() and XMLHttpRequest calls. Headers persist across requests and re-inject after navigation. Useful for auth tokens, API keys, or custom tracking headers.
Command | Description |
| Set one or more custom headers |
| List active custom headers |
| Remove all custom headers and restore original fetch/XHR |
Note: Headers are injected JS-side only (via fetch/XHR interception). They do not affect initial page load requests or non-JS resource fetches.
Page Performance Metrics
Get timing and resource metrics from the Performance API.
Command | Description |
| Show page performance metrics |
Returns: first byte time, DOM interactive, DOM content loaded, load complete, DOM element count, script/stylesheet/image/iframe counts, JS heap memory usage.
Element Attributes
Read, set, or remove HTML attributes on elements.
Command | Description |
| Get one or all attributes |
| Set an attribute |
| Remove an attribute |
Browser Profile Management
Save and restore browser state (cookies + localStorage + URL) as named profiles.
Profiles are stored in ~/.tbp/profiles/<name>/.
Command | Description |
| Save current state as named profile |
| Load saved profile (cookies + localStorage) |
| List all saved profiles |
| Delete a saved profile |
Profile names: Alphanumeric, hyphens, and underscores only.
Element Highlight
Visual debugging — outline matching elements with colored borders.
Command | Description |
| Highlight elements |
| Remove highlights (all or specific) |
Highlights persist across navigation (re-injected after goto).
PDF Export Options
Extended PDF export with layout control.
Option | Description |
| Landscape orientation |
| Scale factor |
| Margins in inches |
| Specific pages |
| Skip background graphics |
Example: tbp pdf report.pdf --landscape --scale 0.8 --margin-top 0.5
Cookie Auth Sessions
Save/restore authentication via cookies — auto-navigates to saved URL.
Command | Description |
| Save cookies + URL as auth session |
| Restore cookies and navigate to saved URL |
| List saved auth sessions |
| Delete auth session |
Sessions stored in ~/.tbp/auth/ with 0o600 permissions.
Network Throttling
Simulate slow connections by adding latency to fetch/XHR requests.
Command | Description |
| Apply throttle preset |
| Custom latency (ms) |
| Remove throttling |
| Show current config |
Presets: 3g (400ms), slow-3g (2000ms), fast-3g (150ms), offline (reject all).
Annotated Screenshot (AI-First)
Screenshot with numbered badges on interactive elements + legend mapping numbers to CSS selectors.
Command | Description |
| Labeled screenshot |
AI workflow: annotate → read legend → click using selector from legend.
Page Audit
One-command structured page health report.
Command | Description |
| Full page health report |
Returns: elements, links (total/external/broken), images (alt/broken), forms, headings, meta, scripts, page size, load time, console errors.
Response Mocking
Return fake responses for matching URL patterns. Useful for testing without real backends.
Command | Description |
| Add mock |
| Remove mock(s) |
| List active mocks |
Mocks persist across navigation (re-injected after goto). Max 50 mocks.
DOM Snapshot & Diff
Save page state, perform actions, then diff to verify changes.
Command | Description |
| Capture page state |
| Compare two snapshots |
| List snapshots |
| Delete snapshot |
AI workflow: snapshot take before → actions → snapshot take after → snapshot diff before after.
Double-click
Command | Description |
| Double-click element (dispatches dblclick event) |
| Use xdotool double-click |
Select Dropdown
Command | Description |
| Select option by value |
| Select option by visible text |
| Select option by index |
Dispatches change + input events for React/Vue compatibility.
Check / Uncheck
Command | Description |
| Check a checkbox or radio |
| Uncheck |
| Toggle |
Input Value
Command | Description |
| Read current value of input/select/textarea |
Returns {value, tag, type}.
Element State
Command | Description |
| Query element visibility/enabled/checked state |
Returns {visible, enabled, checked, editable, tag, type}.
Bounding Box
Command | Description |
| Get element position and dimensions |
Returns {x, y, width, height, top, left, bottom, right, scrollX, scrollY}.
Scroll To Element
Command | Description |
| Scroll element into view (default: center) |
| Align to top |
Block options: center, start, end, nearest.
Set Page Content
Command | Description |
| Replace page with raw HTML (no navigation) |
| Load HTML from file |
Dialog Handling (alert/confirm/prompt)
Auto-handle browser dialogs without blocking. Monkey-patches window.alert/confirm/prompt. Re-injects after navigation.
Command | Description |
| Enable auto-accept for dialogs |
| Auto-dismiss dialogs |
| Set prompt response |
| Shortcut for reject mode |
| Show captured dialog messages |
| Clear dialog log |
Wait for Response
Wait for a fetch/XHR response matching a URL pattern.
Command | Description |
| Wait for matching response |
| Custom timeout (1-120s) |
Enables response capture automatically if not already active.
Multi-step Macros
Chain commands into reusable JSON scripts (max 100 steps).
Command | Description |
| Run macro from JSON file |
Session & Lifecycle
Command | Description |
| Start daemon |
| Graceful shutdown |
| Show daemon status (PID, URL, uptime) |
| Manage cookies |
| List downloaded files |
| Force-kill everything |
Design Philosophy
Be real, not fake. Firefox runs as a normal browser — no geckodriver,
no Marionette, no WebDriver flags. Controlled via xdotool (X11 native
input) and clipboard-based JS execution through the Web Console.
Chromium uses real device hardware info with only webdriver=false hidden.
Architecture
CLI (cli.py) ──Unix socket──→ Daemon (daemon.py)
├── Pilot (unified API)
│ ├── BrowserPilot Xvfb + openbox WM + browser lifecycle
│ ├── NativeFirefoxSession xdotool + clipboard JS (persistent profile)
│ ├── CDPSession WebSocket CDP (Chromium)
│ ├── PageCommands navigate, eval, text/html/links
│ ├── InputCommands click, type, scroll, Bezier mouse
│ ├── ScreenshotCommands PNG, full-page, PDF
│ ├── CookieCommands get/set/save/load/export/import
│ ├── NetworkTracker request capture (Chromium only)
│ ├── Accessibility a11y tree
│ └── CloudflareHandler Turnstile (Chromium only)
├── DeviceInfo auto-detect screen/GPU/CPU/model
└── Stealth CDP-level UA/platform (Chromium)Auto-Detected Device Info
Property | Source | Example |
Model |
| SM-S918B |
Screen | DPI ratio + model DB | 1080x2316 |
GPU |
| Adreno740v2 |
CPU cores |
| 8 |
RAM |
| 11GB |
Architecture |
| aarch64 |
Test Results (2026-02-24)
All 5 test sites pass with Firefox (default):
Site | Result | Notes |
example.com | PASS | Navigation, JS eval, links, text, scroll |
bot.sannysoft.com | PASS | Navigation, scroll |
audiogames.net | PASS | CF bypassed via TLS fingerprint |
nowsecure.nl | PASS | CF bypassed via TLS fingerprint |
platform.openai.com | PASS | Form filling, clipboard paste input |
Firefox vs Chromium
Feature | Firefox | Chromium |
Cloudflare | Instant (TLS) | Turnstile handler |
audiogames.net | PASS | FAIL |
Network tracking | Not available | Full CDP tracking |
JS execution | Console + clipboard | CDP Runtime.evaluate |
Stealth needed | None | UA + WebGL + canvas |
File Structure
termux-browser-pilot/
├── cli.py # CLI entry point (daemon + legacy commands)
├── setup.sh # One-command installer
├── pyproject.toml # Python packaging
├── src/
│ ├── pilot.py # Main unified API + session persistence
│ ├── daemon.py # Persistent browser daemon (Unix socket)
│ ├── client.py # Daemon client (send commands)
│ ├── native.py # Firefox: xdotool + clipboard JS execution
│ ├── browser.py # Xvfb + browser lifecycle
│ ├── cdp.py # CDP WebSocket client (Chromium)
│ ├── commands.py # Page commands (navigate, eval, text, html)
│ ├── input.py # Keyboard/mouse + Bezier human-like input
│ ├── screenshot.py # Screenshot/PDF capture
│ ├── stealth.py # Anti-detection (Chromium only)
│ ├── cookies.py # Cookie management + Netscape import/export
│ ├── cloudflare.py # CF Turnstile handler (Chromium)
│ ├── network.py # Network tracking (Chromium only)
│ ├── accessibility.py # A11y tree access
│ ├── device.py # Real device detection
│ ├── gpu.py # WebGL renderer spoofing
│ ├── lock.py # Session lock (single-instance)
│ ├── _utils.py # Shared utilities (JS escaping, binary checks)
│ └── mcp_server.py # MCP server for Claude Code integration
└── .mcp.json # Claude Code auto-discovery configRequirements
Termux on Android (aarch64)
Firefox mode:
firefox,xorg-server-xvfb,xdotool,xclip,openbox,python3Chromium mode:
chromium,xorg-server-xvfb,mesa,python3,websockets>=12.0openbox(lightweight WM) is required for reliable keyboard shortcut routing in Xvfb
Troubleshooting
SSL Certificate Errors (Firefox)
If Firefox shows "Warning: Potential Security Risk Ahead" on HTTPS sites, it means
Firefox isn't using Termux's system CA certificates. The daemon automatically fixes
this on startup (v0.17.2+), but if you're on an older version or have an existing
profile, add this to ~/.tbp/firefox_profile/user.js:
user_pref("security.enterprise_roots.enabled", true);Then restart the daemon:
tbp stop
tbp goto https://example.com # auto-starts with fix appliedMake sure the ca-certificates package is installed:
pkg install ca-certificatesDaemon Won't Start
If the daemon fails to start, check the log:
cat ~/.tbp/daemon.logCommon fixes:
Kill stale processes:
pkill -f Xvfb; pkill -f firefox; rm ~/.tbp/daemon.pid ~/.tbp/daemon.sockEnsure Xvfb is installed:
pkg install xorg-server-xvfb
License
MIT
This server cannot be deployed
Maintenance
Related MCP Connectors
Programmatic headless browser sessions: create, interact, browse, and extract - rendered in a real
I do everything related to Browser Automation & Management
Automate cloud Chrome—navigate, click, type, screenshot, run code, record screen video
Headless-browser-as-JSON with memorymarket cache economics. Real Chromium, crypto settlement.
Related MCP Servers
- FlicenseAqualityAmaintenanceFirefox browser automation via WebDriver BiDi for testing, scraping, and browser control. Supports snapshot/UID-based interactions, network monitoring, console capture, and screenshots.343,582 npm431-
- FlicenseAqualityDmaintenanceMCP server for automating qutebrowser browser via CDP and IPC. Enables tab management, navigation, screenshots, JavaScript execution, and authenticated HTTP requests through the browser's session.16-
- AlicenseBqualityDmaintenanceEnables Puppeteer-based web automation (navigation, screenshots, PDF generation, JavaScript execution, clicking) on Android Termux by running Chromium inside an Alpine Linux container.91MIT
- AlicenseAqualityCmaintenanceDrive Firefox-based browsers (Floorp, LibreWolf, Zen, Waterfox, Mullvad, Firefox) from any MCP client — read pages, screenshot, click, fill forms and manage tabs in your real session, over Marionette/WebDriver. OS input & JS eval locked by default.4143 npm2MIT