Termux Browser Pilot
Click on "Install 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
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 installed
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/salviz/termux-browser-pilot'
If you have feedback or need assistance with the MCP directory API, please join our Discord server