reactive-resume
reactive-resume
A one-of-a-kind resume builder that keeps your privacy in mind. Completely secure, customizable, portable, open-source and free forever. Try it out today!
yinnho/aginxbrowser
The browser built for AI agents — fetch live pages as markdown, render JS/SPAs with built-in V8, take screenshots without Chromium, meta-search 5 engines, and drive interactive login sessions. One Rust binary, stealth TLS fingerprints, MCP native for Claude Code & Cursor. Headless browser alternative to Puppeteer/Playwright.
PROJECT TOPICS
INSTALL REFERENCE
dsh plugin --profile web add github:yinnho/aginxbrowser
该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。
PROJECT README
English | 中���
The Browser for AI Agents. See the live web. Read it. Act on it. Remember it.
A browser built for agents from the first line of code — not a human browser bolted onto automation. See the world, read it, search it, act on it, and keep what you read: one Rust binary with built-in V8, no Chromium required.
Humans have Chrome. Agents have AginxBrowser.
One binary, zero dependencies, instant service. HTTP API + native MCP + CDP — agents plug in and go, and existing Playwright / Puppeteer / browser-use code attaches directly.
Real pages rendered by AginxBrowser's diting engine (no Chromium) — Wikipedia, this repo, Rust. Screenshot it yourself →

Measured against headless Chrome on the same 20 pages, same network (bench, 2026-08-28): 7.6× faster to agent-usable text (p50 532 ms vs 4 053 ms), ~10× less memory (227 MB for the whole process vs ~2.1 GB per Chrome page), and 0 hard failures where Chrome's --dump-dom produced no DOM on 5 of 40 loads. An agent's total cost is browser efficiency × model efficiency — this is the browser half.
Existing "browser automation" was built for humans or for one-shot scraping — not for agents:
| AginxBrowser | Puppeteer/Playwright | Firecrawl | Browser-use | |
|---|---|---|---|---|
| Designed for | Agents first | Human debugging | Scraping service | LLM wrapper |
| Dependencies | Single binary, no Chromium | Chromium ~500MB | Docker ~1GB | Chromium |
| Sees (screenshots) | ✅ built-in diting rendering engine | Needs Chromium | ❌ | Needs Chromium |
| Reads | markdown + js_extract + fetch receipts | DIY | markdown | DIY |
| Writes documents | ✅ render_markdown: deterministic HTML + inline-SVG diagrams |
❌ | ❌ | ❌ |
| Finds (search) | ✅ 15 engines, 7 categories, merged | ❌ | ❌ | ❌ |
| Acts | indexed session interaction | DevTools API | ❌ | LLM-driven |
| Remembers | ✅ local fetch/search cache (SQLite FTS5) | ❌ | crawl cache | ❌ |
| Protocol | HTTP + native MCP + CDP | Node API | HTTP | Python |
| TLS fingerprints | ✅ Chrome/Firefox/Safari/Edge | Plugin required | ❌ | ❌ |
| CAPTCHA | ✅ detect + auto-wait + optional 2captcha | DIY | ❌ | ❌ |
| Interactive sessions | ✅ persistent | ✅ | ❌ | ✅ |
An agent needs five things from a browser: see, read, find, act, remember. One binary covers them all — systemd-friendly, MCP-native for Claude/Cursor, zero dependencies.
Core advantage: no Chromium. AginxBrowser inlines a full browser engine (V8 + Rust HTTP stack + the diting CSS/layout/paint rendering engine, with the Blitz/Stylo/Taffy lineage as its reference implementation). No Puppeteer, no Chrome, no Docker. One Rust binary under systemd is your agent browsing infrastructure.
Most new "agent browsers" are stateless, fingerprint-less one-shot renderers — fine for public pages, dead on arrival against Cloudflare or login flows. AginxBrowser goes the opposite way:
cf_clearance. Fingerprint-less engines eat 403s — we get through.session_create(cookies=...) ↔ session_cookies), surviving pagination and multi-step flows; persistent: true even survives idle eviction and server restarts — the same session id comes back logged in. One-shot engines throw state away.Reference point: Cloudflare's Kitesurf explicitly ships neither real TLS-fingerprint negotiation nor persistent auth sessions — anti-bot and login territory is exactly where AginxBrowser plays.
Apache-2.0 open source, single binary — self-host today, no cloud lock-in.
Agents act on what a browser tells them, so the response reports what actually happened — not just "got a 200":
tier — which path served the page: plain HTTP (~100 ms) or the V8-rendered browser tier. An agent can see why a fetch was fast or slow.redirected_from — the full redirect trail. redirected_from[0] is the URL you asked for, url is where the content actually came from — requested paired with effective, every hop visible.content_hash + changed_since_prev — every fetch is hashed; consecutive samples of the same URL can be diffed. A rate-limited origin serving the same frozen 200 body for days reads as changed_since_prev: false — the cheapest drift detector there is.captcha_event — when a challenge page was detected (and solved, if a solver is configured), the response says so instead of handing over a challenge page as if it were content.The local cache builds on the same idea: search hits come back with [§ heading] section prefixes so an agent knows where on the page a hit landed, and ranking fuses keyword relevance with freshness.
tier field)/search. Search → read in one stepcategories=images hits Baidu/Bing image indexes and returns direct binary image_url links (downloadable straight to jpg/png) plus source_url provenancestate/click/input/scroll/eval) — agents browse like humans do, and session_export turns what an agent figured out into a runnable curl replay script (zero model tokens on re-run) — or, with format=json, into a flow document (flow_run replays it server-side with {{var}} substitution, wait/expect gates and saved outputs; installed flows live in workflow/<name>/flow.json, dropped in without a rebuild). Session tools also cover the acting part: session_viewport simulates device viewports (media queries respond), session_wait blocks on a selector or predicate with a timeout, session_screenshot renders the live state, session_console replays the page's console ring, and session_storage exports/restores cookies plus localStorage for login hand-offsession_network(filter=media) extracts the m3u8/mp4/dash URLs a page's player actually requested at runtime — links found only in page HTML are often decoys, so the request log is the source of truth. GET /session/{id}/har exports the same traffic as HAR 1.2 (retained bodies included)/json/version + /devtools/{kind}/{id} WebSocket — chromium.connectOverCDP() from Playwright, Puppeteer, or browser-use attaches with one line, and agent-browser drives it via --cdp (snapshot returns the synthesized accessibility tree with @ref handles) (integration guide). DevTools ecosystem compatibility without becoming a CDP shim~/.aginxbrowser/cache.db. The cache tool re-answers from what the agent already read instead of re-paying network time: full-text search with CJK substring matching, keyword × freshness fusion ranking, [§ heading] section-aware snippets, per-URL content hashes for drift detection, TTL-bounded, per-session scoping for shared deploymentsjs_extract pulls window.__INITIAL_STATE__ and other structured data out of SPAsrender_markdown turns markdown into a deterministic, self-contained HTML artifact — the document layer, so agents never write HTML by hand. Prose rides a plain offline shell (no fonts, no scripts); fenced archify blocks carry typed zero-coordinate diagram JSON (sequence / workflow / architecture / dataflow / lifecycle families) and render to inline SVG via the layout engine. Same input, same bytes — the receipt carries the sha256 so determinism is verifiable. theme (light/dark) and preset (classic / signal-flow / blueprint / editorial) bake colors at generation time; quality: "showcase" is the delivery gate, grading route crossings, label clearance and rhythm without touching the artifact bytes. Guided-view tabs plus window.agxViewer (focus / ego / route / reach) make the artifact interactive; with session_id it loads into a live session and the reply grades how it fits the viewport (fits/tall/wide/oversized). Mermaid sources are the agent's job to translate into archify JSON, not the engine's. Diagram vocabulary adapted from archify (MIT)/screenshot endpoint (opt-in --features screenshot) paints the JS-rendered DOM with the diting rendering engine — pure CPU, no Chromium — to PNG. Vision input for agents/video endpoint + render_video MCP tool render a page's animation timelines to MP4 — the page's scripts register GSAP-style timelines in window.__timelines (duration() + pause(t)), each frame seeks to t=i/fps and paints the viewport, and the frames pipe into ffmpeg (H.264, yuv420p). Deterministic by construction: no wall clock in the pixel values, same render twice = same MP4. Needs ffmpeg on PATH/pdf endpoint + render_pdf MCP tool cut a rendered page into pages and package them — print mode paginates at top-level block boundaries (default A4 @96dpi, no half-cut text where a break can land on a block edge), slides mode makes one page per CSS-selector match sized to the element (an HTML deck with one .slide per page exports as a real deck). Image-based PDF: per-page JPEG via DCTDecode, hand-rolled PDF 1.4 writer, zero new dependencies. PPTX packages the same pages as one slide per page; DOCX as one page-sized section per page — both hand-rolled OOXML (stored-ZIP writer, fixed timestamps), byte-deterministic, zero new dependencies--mcp mode exposes 37 tools (fetch/eval/search/download/cache + session + flow + screenshot + video/pdf + docgen tools) — Claude Code / Claude Desktop / Cursor call them directly/v1/scrape endpoint — existing Firecrawl clients migrate by changing the base URLAginxBrowser exists for real-time retrieval: an agent arrives with a question, reads a handful of pages, leaves with the answer. It is not a crawling tool — and the product is shaped so it can't quietly become one:
AGINXBROWSER_HONOR_ROBOTS=1.AGINXBROWSER_DOMAIN_RATE_PER_MIN / AGINXBROWSER_SESSION_PAGE_LIMIT (0 disables on your own instance). Generous for an agent grinding through docs or a console; fatal to the page-after-page crawl pattern, including subdomain rotation (one registrable domain, one budget).Not demos — real jobs agent browsers are doing today:
Computer-use agents come in two layers. GUI-layer stacks (Cua, desktop CUA agents) drive a whole machine: screenshots of a display in, X11 mouse/keyboard events out, a VM or container per session. Engine-layer browsers skip the desktop — the page itself is the machine. AginxBrowser is the engine layer:
| GUI layer (desktop CUA) | AginxBrowser (engine layer) | |
|---|---|---|
| Action space | screen pixels → OS input events | DOM/CDP: click by coordinates or selector, real event dispatch |
| State readout | screenshot of a display | structured DOM / accessibility tree, screenshot optional |
| Per-session cost | Xvfb + VM/container | one process, no display server |
| Frames | flattened into pixels | first-class: hit-testing descends into iframes, frame-scoped evaluate |
| Replay | best-effort (compositor timing) | action logs export as runnable curl / flow JSON |
Validated against the GUI layer's own harness: the cua-bench webtop gym — a window manager where every "window" is an iframe — runs on AginxBrowser through the CDP bridge (click task: PASS end-to-end). That's the path that exercises iframe hit-testing, frame-scoped script state, and coordinate translation, which is exactly where engine-layer substitutes usually break. browser-use attaches the same way Playwright does: point cdp_url at the bridge.
Try the hosted instance first: https://browser.aginx.net/
One-command full install (SKILL.md trigger surface + MCP tools + verification):
# Download -> inspect the contents -> run only after review (never blind-run network scripts)
curl -fsSL https://raw.githubusercontent.com/yinnho/aginxbrowser/main/skill.sh -o skill.sh
less skill.sh
bash skill.sh
Register MCP only:
claude mcp add aginxbrowser --transport http https://browser.aginx.net/mcp
Install the skill trigger surface via skills.sh:
npx skills add yinnho/aginxbrowser
Or just hand this block to your AI agent — it sets itself up:
Set up aginxbrowser as your web access layer:
1. Register the MCP server (skip if already present):
claude mcp add aginxbrowser --transport http https://browser.aginx.net/mcp
No claude CLI? The HTTP API works directly — no MCP needed.
2. Verify capabilities at https://browser.aginx.net/doctor before calling
feature-gated endpoints (screenshot/stealth must be listed).
3. From now on, route web tasks through it instead of raw curl:
- read a page / scrape a URL -> fetch {url} (markdown output, Cloudflare bypassed by default)
- search the web -> search {q, fetch_top:3} (5 engines incl. Baidu/WeChat)
- see a page -> screenshot {url}
- login / form / click-through-> session_create -> session_state -> session_input/session_click -> session_close
Self-hosting:
# macOS / Linux via Homebrew
brew install yinnho/aginxbrowser/aginxbrowser
aginxbrowser doctor # features + fonts + egress self-check
# Docker (Docker Hub, mirrored on GHCR)
docker run -p 8089:8089 yinnho/aginxbrowser:latest
# (or ghcr.io/yinnho/aginxbrowser:latest)
# Or the prebuilt binary (platform detect + sha256 + mirror fallback + doctor self-check)
# macOS / Linux / Windows (git-bash; prebuilt Windows ships from v0.3.1, full `stealth`+`screenshot` feature set from v0.4.0)
# Cautious: download -> inspect -> run (never blind-run network scripts)
curl -fsSL https://browser.aginx.net/install.sh -o install.sh
less install.sh && bash install.sh
# Or straight in, if you trust the repo:
# curl -fsSL https://browser.aginx.net/install.sh | sh
# GitHub slow/blocked? AGINXBROWSER_GH_PROXY=https://ghfast.top/ bash install.sh
aginxbrowser doctor # features + fonts + egress self-check
# Or build from source (--features stealth,screenshot or you lose both)
cargo build --release --features stealth,screenshot
# Start the service
./target/release/aginxbrowser
# → Listening on 0.0.0.0:8089
# Verify
curl http://127.0.0.1:8089/health
# → {"status":"ok","engine":"diting"}
# Fetch a page
curl -sS -X POST http://127.0.0.1:8089/fetch \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com"}'
# Search (snippets only by default; fetch_top grabs page bodies for the top N)
curl -sS -X POST http://127.0.0.1:8089/search \
-H "Content-Type: application/json" \
-d '{"q":"macbook price","max_results":5,"fetch_top":2,"max_chars_per":2000}'
# Create an interactive session
curl -sS -X POST http://127.0.0.1:8089/session/create \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com"}'
# → {"session_id":"s_1","url":"https://example.com/"}
# MCP mode (for AI agents)
./target/release/aginxbrowser --mcp
Every capability is plain HTTP — no SDK required. There is no /openapi.json (the routes are few enough to list here); full request/response fields for each route are in docs/API.md.
| Method | Path | What it does |
|---|---|---|
| GET | /health |
Liveness + build commit, UA, TLS, capabilities |
| GET | /doctor |
Deep self-check: engines live, fonts, egress |
| GET | /engines |
Search engine catalog with live suspension state |
| POST | /fetch |
Fetch a page → text/markdown/html. Params: render_tier (auto/http/browser), max_chars, capture_xhr, … |
| POST | /search |
Multi-engine meta-search. Params: engines, categories, max_results, time_range (day/week/month/year), fetch_top, max_chars_per, wait_secs |
| POST | /click |
Click a CSS selector on a page |
| POST | /eval |
Evaluate JavaScript on a page |
| POST | /download |
Stream a file to disk (sha256, resume) |
| POST | /screenshot |
Render page → PNG (screenshot feature) |
| POST | /video |
Render animation timelines → MP4 (screenshot feature) |
| POST | /pdf |
Paginate page → PDF/PNG/PPTX/DOCX (screenshot feature) |
| POST | /v1/scrape |
Firecrawl-compatible scrape (+ actions) |
| POST | /flow/run |
Run a recorded/edited flow JSON to completion — zero model tokens (name runs an installed workflow/<name>/flow.json, flow is inline, vars substitute {{placeholders}}, session_id composes with imported login state) |
| POST | /session/create |
Start an interactive session (cookies/UA carried across calls) |
| POST | /import/curl |
Create a logged-in session from a DevTools "Copy as cURL" |
| GET | /session/list |
Live sessions |
| POST | /session/{id}/navigate · /state · /click · /click_xy · /drag · /input · /scroll · /eval · /wait · /dialog · /viewport · /screenshot · /clone · /close |
Session actions |
| GET | /session/{id}/cookies · /storage · /console · /network · /har · /export |
Session inspection |
| GET | /json/version · /json/list · /devtools/… |
CDP bridge (Playwright/Puppeteer connect here) |
| POST | /mcp |
MCP endpoint (--mcp mode serves stdio) |
Two MCP tools have no REST route: cache (query the local fetch/search cache) and render_markdown (markdown → deterministic HTML artifact). Everything an agent does through MCP is callable over REST above.
aginxbrowser/
├── Cargo.toml
├── build.rs # V8 snapshot generation
├── js/
│ └── bootstrap.js # V8 bootstrap script
├── workflow/ # Flow assets: <name>/flow.json replayed by flow_run (drop-in, no rebuild)
├── README.md
├── docs/
│ ├── API.md # Full API reference (HTTP + MCP)
│ └── integrations.md # CDP bridge: Playwright / Puppeteer / browser-use
├── bench/ # Benchmark harness + results (vs headless Chrome)
│ ├── README.md # methodology + numbers
│ ├── pages.txt # fixed 20-page set
│ ├── run.py # harness
│ ├── summarize.py # TSV → results table
│ └── results/ # raw run data
└── src/
├── main.rs # HTTP service entry & routing
├── server.rs # Business layer (fetch/click/eval/search)
├── session.rs # Interactive browser sessions
├── mcp.rs # MCP server (37 tools)
├── docgen/ # Document layer: markdown → deterministic HTML + inline-SVG diagrams
├── render.rs # Tiered rendering (HTTP direct → diting browser engine)
├── store.rs # Local fetch/search cache (SQLite FTS5, drift hashes)
├── download.rs # Streaming file download (sha256, resume)
├── robots.rs # RFC 9309 robots.txt checker (opt-in gate)
├── rate.rs # Per-domain + per-session budgets
├── captcha.rs # CAPTCHA detection & auto-solve
├── firecrawl_compat.rs # Firecrawl-compatible /v1/scrape endpoint
├── video.rs # Timeline video pump (__timelines seek → ffmpeg → MP4)
├── pages.rs # Page pump (print/slides pagination → PDF/PNG)
├── ooxml.rs # OOXML containers (image-based PPTX/DOCX, stored-ZIP writer)
├── diting_cdp/ # CDP bridge (DevTools HTTP + WebSocket)
├── doctor_cli.rs # `aginxbrowser doctor` self-check
├── browser.rs # Top-level API: Browser, BrowserBuilder
├── page.rs # Top-level API: Page, Element
├── config.rs # BrowserConfig
├── cookie.rs # CookieStore
├── error.rs # Error types
├── search/ # 15 native search engines, 7 categories
│ ├── mod.rs # SearchEngine trait, Registry, merge/dedupe, progressive backoff
│ ├── baidu.rs # Baidu (JSON API, wreq stealth)
│ ├── baidu_images.rs # Baidu Images (acjson API, images category)
│ ├── bing.rs # Bing (HTML parsing, plain reqwest)
│ ├── bing_images.rs # Bing Images (images/async endpoint, images category)
│ ├── bing_news.rs # Bing News RSS (news category; proxy-first)
│ ├── sogou.rs # Sogou web (HTML parsing, plain reqwest)
│ ├── sogou_wechat.rs # Sogou WeChat (HTML parsing + /link resolution)
│ ├── duckduckgo.rs # DuckDuckGo (html.duckduckgo.com, general; direct-first)
│ ├── google.rs # Google (HTML parsing, wreq stealth + proxy)
│ ├── stackexchange.rs # Stack Overflow (SE API v2.3, code category)
│ ├── github_repos.rs # GitHub repos (api.github.com, code category)
│ ├── arxiv.rs # arXiv (Atom API, academic category)
│ ├── huggingface.rs # HF Hub models/datasets/spaces (ai category)
│ ├── npm.rs # npm packages (npms.io API, packages category)
│ ├── pypi.rs # PyPI name resolution (JSON API, packages)
│ └── meilisearch.rs # Private-index adapter (env-configured)
│
├── diting_dom/ # HTML parsing, DOM tree, CSS selectors
├── diting_css/ # CSS parsing + cascade
├── diting_net/ # HTTP client, cookies, encoding, proxies
├── diting_js/ # V8 runtime, JS ops, module loading
├── diting_layout/ # Taffy-based layout, floats, hit-testing
├── diting_fonts/ # Bundled CJK font subset, fallback
└── diting_browser/ # Page navigation, lifecycle, browser context
# Standard build (no stealth; TLS fingerprint features inactive)
cargo build --release
# With stealth (requires go + cmake + C++ toolchain; enables TLS fingerprint spoofing)
cargo build --release --features stealth
# With screenshot rendering (enables /screenshot; adds the rendering stack, +30-40MB)
cargo build --release --features screenshot
# Full featured (recommended for production)
cargo build --release --features stealth,screenshot
Requirements: Rust 1.78+; the V8 static library downloads automatically on first build. The stealth feature additionally needs go, cmake, and a C++ compiler. The screenshot feature ships with a bundled CJK font subset (GB2312 + common symbols) — no system fonts required for correct Chinese rendering.
If your network can't reach the rusty_v8 CDN (build hangs with zero progress after "downloading v8"), pre-fill ~/.cache/rusty_v8 with the librusty_v8.a.gz for your version (fetch it from any reachable mirror/host and gunzip into place) and the build script skips the download.
| Variable | Default | Description |
|---|---|---|
AGINXBROWSER_BIND |
0.0.0.0:8089 |
Listen address |
--cdp-port N (flag) |
unset | Bind on 127.0.0.1:N instead — the local agent-tooling entry (agent-browser --cdp N, Playwright connectOverCDP). Beats AGINXBROWSER_BIND when both are set |
AGINXBROWSER_STEALTH |
enabled | 0 disables stealth (for diagnostics) |
AGINXBROWSER_UA |
Linux Chrome145 | Spoofed User-Agent |
AGINXBROWSER_ACCEPT_LANGUAGE |
zh-CN,zh;q=0.9,en;q=0.8 |
Accept-Language header |
AGINXBROWSER_PROXY |
none | Optional fallback proxy. Blocked-source engines (Google, Bing News, Hugging Face) connect directly first and fall through to this proxy only when the direct attempt fails — overseas deployments need no proxy at all; per-request use_proxy:true also routes fetch/search through it. Browser/session/CDP navigations to known-blocked domains (wikipedia.org, github.com, …) route through it automatically. Standard HTTP_PROXY/HTTPS_PROXY/ALL_PROXY are deliberately ignored by the engine (set them for other tools freely); startup logs a warning when it sees one |
AGINXBROWSER_NAV_CHAIN_LIMIT |
10 |
JS navigation-chain cap: documents a page may chain via location/form hops before navigation aborts. The count includes the requested document (10 = initial doc + 9 hops). Raise for legit long chains (SSO handover across providers); HTTP 3xx redirects are budgeted separately (20, per Fetch spec / browser parity) |
AGINXBROWSER_CACHE_TTL_SECS |
600 |
/fetch cache TTL, 0 disables |
AGINXBROWSER_HONOR_ROBOTS |
unset | robots.txt is not consulted by default on /fetch, /screenshot, /download and MCP tools; set 1 to opt in (operator choice) |
AGINXBROWSER_ALLOW_FILE_ACCESS |
unset | Opt in to file:// reads — navigation, subresources, /fetch, and CDP setFileInputFiles. Same as the --allow-file-access CLI flag. Off by default: the server binds 0.0.0.0, so an open gate hands local files to anyone who can reach the port. Set it on a local dev instance, not a hosted one |
AGINXBROWSER_ALLOW_PRIVATE_NETWORK |
unset | Opt in to loopback/RFC1918/link-local fetches (the SSRF gate). Same as the --allow-private-network CLI flag — dev machines only |
AGINXBROWSER_ALLOW_NETWORK |
unset | Scoped alternative: comma-separated CIDR allowlist (e.g. 10.20.0.0/16,192.168.1.0/24) that opens just those ranges — cloud-metadata endpoints (169.254.169.254, 100.100.100.200) and everything else stay blocked. Same as --allow-network <cidrs> |
AGINXBROWSER_FONT_DIR |
unset | Directory of extra fonts (.ttf/.otf/.ttc) loaded as tail fallbacks for scripts the bundled CJK subset doesn't cover (Korean, Thai, Arabic, …). Same as the --font-dir <path> CLI flag. Faces the bundle already covers keep bundle rendering — dir fonts are coverage tails, not named-family overrides |
AGINXBROWSER_ROBOTS_TTL_SECS |
3600 |
Per-host robots.txt policy cache TTL |
AGINXBROWSER_DOMAIN_RATE_PER_MIN |
20 |
Per-registrable-domain page budget per minute (subdomains share one budget); over-budget requests get 429 with the stance message. 0 disables. See "A Browser, Not a Crawler" |
AGINXBROWSER_SESSION_PAGE_LIMIT |
200 |
Total pages one interactive session may walk (navigation-causing clicks count); over-budget navigations are refused, the current page stays interactive. 0 disables |
AGINXBROWSER_MCP_ALLOWED_HOSTS |
unset | Extra Host values accepted by /mcp (comma-separated) — the transport's DNS-rebinding guard defaults to loopback, so add your LAN IP or Docker hostname when other machines call the instance |
AGINXBROWSER_STORE |
on | Local fetch/search cache; 0/false/off disables |
AGINXBROWSER_STORE_PATH |
~/.aginxbrowser/cache.db |
SQLite database location (created 0600) |
AGINXBROWSER_STORE_TTL_HOURS |
720 |
Cached page TTL |
AGINXBROWSER_STORE_SEARCH_TTL_HOURS |
168 |
Cached search-result-set TTL |
AGINXBROWSER_STORE_SCOPE |
global |
session gives each MCP client session its own cache scope — set this on public multi-client deployments |
CAPTCHA_SOLVER_API_KEY |
none | 2captcha API key; enables CAPTCHA auto-solving |
CAPTCHA_SOLVER_SERVICE |
2captcha |
CAPTCHA solving provider |
AGINXBROWSER_MEILI_URL |
none | Meilisearch base URL; set to enable the private-index engine |
AGINXBROWSER_MEILI_INDEX |
none | Meilisearch index uid to query |
AGINXBROWSER_MEILI_KEY |
none | Optional Bearer key for the Meilisearch instance |
Full API reference → docs/API.md
CDP integration guide → docs/integrations.md — Playwright / Puppeteer / browser-use one-liners
Security audit notes → docs/skills-sh-audit.md — why skills.sh shows "Critical Risk", and which real product feature each warning corresponds to
Covers:
/fetch, /search, /screenshot, /video, /pdf, /download, /v1/scrape, /flow/run, /doctor, 19 session endpoints, CDP discovery, MCP transport)AginxBrowser is pure attach-alongside infrastructure — like a real browser, it runs as an independent service that anything can call, without embedding host code or polluting host config. Deploy one instance per machine (under systemd) and every app needing "render + scrape" capability shares it.
Three attach points:
/fetch, /search, /screenshot, /download for any language with an HTTP clientws://your-host:8089/devtools/browser/<id>; agent-browser drives it with --cdp (--cdp-port N binds loopback for that). Google's chrome-devtools-mcp attaches too: aginxbrowser --cdp-port 9223 + chrome-devtools-mcp --browser-url http://127.0.0.1:9223 — its full tool battery (pages, snapshot, evaluate, screenshot, network, resize) passes against the diting engine. See docs/integrations.mdIntegration: read the environment variable AGINXBROWSER_URL=http://127.0.0.1:8089. Unset → behavior unchanged; set → risk-controlled sites automatically route through AginxBrowser for rendering, falling back gracefully on failure.
/screenshot requires cargo build --release --features screenshot (adds the diting rendering stack). The default (and only) render engine in that build is diting — our own CSS+layout+paint stack, zero Blitz/Stylo code. The pinned-rev Blitz reference pipeline is a separate opt-in, --features blitz-reference, for comparison renders and the dual-engine cross-check tests. Complex-site CSS is approximate on both (not pixel-perfect like Chromium)/screenshot with selector returns element page coordinates (selector_rects, CSS px); selector alone crops directly to that element. Inline elements (<a>text</a>) get a rect too on the default diting engine — a union of their flattened inline content, strut-expanded to the element's own line-height like Chrome reports for replaced-only inlines (<a><img></a> → line-box height, not the image height). Empty inlines still have no rect — pick a block ancestor theresrc/href resolve to absolute URLs so Next.js/webpack hydrate and clicks trigger handlers). Heavy-fingerprint auth pages (WorkOS/Cloudflare) probing navigator.plugins, WebGL canvas etc. may still break until stealth fingerprint coverage completesAGINXBROWSER_PROXY__zse_ckIf AginxBrowser saved you a headless-Chrome fleet or a scraping headache, a star is how other agents (and their humans) find the project.
Apache-2.0.
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: claude-code、mcp、mcp-server、model-context-protocol、puppeteer-alternative。