Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

unbrowser by Unchained

PYPI · PYUNBROWSER · SCANNED SEP 20

Chrome-free MCP web access for agents with low-token page maps and browser escalation hints.

Available components

+2 this week 65 Trust /100
Trust breakdown (7 categories)

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →

Supply Chain Security38
  • Malware scan not yet available for this package.Unverified
  • No known CVEs affecting this package version or its production dependencies.Pass
  • Install-script risk not yet assessed.Unverified
  • No production dependencies, so there is no dependency health to assess. View diagnostics → Pass
Provenance & Transparency45
Schema Quality & AI Usability80
  • AI-judged instruction clarity (excellent).Pass
  • Context-footprint check failed: tool/resource definitions use about 4208 tokens (~127/item across 33 items; 33 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management100
  • No destabilizing schema changes in the last 30 days.Pass
Tool Coverage100
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 100% of tool parameters carry a description.Pass
Tool Safety100
  • No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
  • All 3 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
  • An AI judge read all 34 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities60
  • Spec-recency check failed: implements MCP spec 2025-06-18; the latest is 2026-07-28. See how to fix → Fail
Install

How do I install the unbrowser by Unchained MCP server?

unbrowser by Unchained runs locally as a PyPI package, launched with uvx pyunbrowser. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

pypi · pyunbrowser

# add to Claude Code
claude mcp add protostatis-unbrowser -- uvx pyunbrowser
// .cursor/mcp.json
{
  "mcpServers": {
    "protostatis-unbrowser": {
      "command": "uvx",
      "args": [
        "pyunbrowser"
      ]
    }
  }
}
// .vscode/mcp.json
{
  "servers": {
    "protostatis-unbrowser": {
      "command": "uvx",
      "args": [
        "pyunbrowser"
      ]
    }
  }
}
# add to Codex CLI
codex mcp add protostatis-unbrowser -- uvx pyunbrowser
// opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "protostatis-unbrowser": {
      "type": "local",
      "command": [
        "uvx",
        "pyunbrowser"
      ],
      "enabled": true
    }
  }
}
# add to OpenClaw
openclaw mcp add protostatis-unbrowser --command uvx --arg pyunbrowser
# ~/.hermes/config.yaml
mcp_servers:
  protostatis-unbrowser:
    command: "uvx"
    args: ["pyunbrowser"]
// ~/.netclaw/config/netclaw.json
{
  "McpServers": {
    "protostatis-unbrowser": {
      "Transport": "stdio",
      "Command": "uvx",
      "Arguments": [
        "pyunbrowser"
      ]
    }
  }
}
# add to Vellum
assistant mcp add protostatis-unbrowser -t stdio -c uvx -a pyunbrowser
// mcp.json
{
  "mcpServers": {
    "protostatis-unbrowser": {
      "command": "uvx",
      "args": [
        "pyunbrowser"
      ]
    }
  }
}
Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 20 Sept 26 0
    • Stability: 0.97 → pass security
  • 19 Sept 26 0
    • Stability: pass → 0.97 functional
  • 18 Sept 26 0
    • Stability: 0.97 → pass security
  • 17 Sept 26 −14
    • Malware scan: pass → unverified security
  • 16 Sept 26 +15
    • Malware scan: unverified → pass security
  • 15 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 87 to 90. That category is still filling its 30-day observation window: 26 days of observed history at the previous scan, 27 at this one. The score rises as the window fills, whether or not the server changes.

  • 13 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 80 to 83. That category is still filling its 30-day observation window: 24 days of observed history at the previous scan, 25 at this one. The score rises as the window fills, whether or not the server changes.

  • 12 Sept 26 −3
    • Stability: pass → 0.80 functional
Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 20 Sept 2026 · Analysed pypi/pyunbrowser@0.0.21

Provenance No attestation

The registry publishes no build provenance for this version, so there is nothing to verify.

Result No attestation
Ecosystem pypi

Background: How many MCP packages publish verified provenance →

Dependencies 0 packages
Packages resolved 0
Tree resolution Complete

Background: SBOMs and build attestations, explained →

MCP tools · 33 exposed · ~4,113 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →

Tool Tokens
activate ~92

Higher-level action probe. Clicks an element by ref or visible action text, settles, and returns before/after URL, BlockMap/page_model summaries, network counts, hashes, and classification: navigated, dom_changed, network_changed, no_effect, or unsupported.

NameTypeReqDescription
refstringOptional element ref like e:142.
textstringOptional visible action text to locate when ref is omitted.

No output schema declared.

No examples provided.

blockmap ~40

Recompute the BlockMap for the current page. Use after eval'd JS or click/type modifies the DOM. Same shape as the inline blockmap from navigate.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

body ~43

Return the raw HTML body of the last navigation. Use as a fallback when the BlockMap or selectors aren't enough — but the response can be large (often 100KB+).

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

click ~91

Dispatch a click event on the element at `ref` (e.g. e:142, returned from query). If the element is <a href> and the click was not preventDefault'd, auto-follows the href via navigate (returns the full navigation result with new BlockMap). Otherwise returns {ok, ref, tag, follow: null}.

NameTypeReqDescription
refstringyesElement ref like e:142

No output schema declared.

No examples provided.

cookies_clear ~15

Drop all cookies from the jar.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

cookies_get ~43

Return all cookies currently in the jar as [{name, value, domain, path, secure, http_only}]. Use this to export cookies to disk for a later session.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

cookies_set ~124

Add cookies to the session jar. Each item is an object {name, value, domain, path?, secure?, http_only?, url?} or a raw Set-Cookie string. Continue using session state from a user-authorized browser, where permitted, by replaying a clearance cookie (e.g. PerimeterX _px3) acquired in real Chrome — requires explicit user confirmation and origin-scoped, ephemeral storage.

NameTypeReqDescription
cookiesarrayyesArray of cookie objects or Set-Cookie strings
urlstringDefault URL for cookies that don't specify domain

No output schema declared.

No examples provided.

discover ~228

High-level cheap-first information discovery. Optionally navigates to a URL, runs light JS, merges DOM routes, inferred form/query URLs, and network JSON routes into one ranked graph with provenance plus route-level escalation hints. Use this when the task is to find where information lives before extracting it.

NameTypeReqDescription
debugbooleanIf true, include full nested navigate, route_discover, and network_extract payloads. Default false returns compact summaries.
exec_scriptsbooleanRun page scripts during navigation when url is provided. Default false; enable when static discovery is insufficient.
goalstringOptional goal/query used to rank routes and build query URLs.
include_networkbooleanInclude captured network JSON objects and API-like captures. Default true.
limitintegerMax routes to return after dedupe/ranking, 1-200 (default 50).
same_originbooleanIf true, only return page-owned routes.
urlstringOptional absolute http(s) URL to navigate before discovery. If omitted, discovers on the current page.

No output schema declared.

No examples provided.

eval ~95

Run arbitrary JavaScript in the embedded QuickJS runtime against the current page's parsed DOM. Returns the JSON-stringified result. Power tool — prefer query/text/blockmap when the CSS selector engine can express what you need. Canonical param is code; raw JSON-RPC also accepts script or expression aliases and errors if no code-like param is present.

NameTypeReqDescription
codestringyesJS code; the value of the last expression is returned

No output schema declared.

No examples provided.

extract ~158

Auto-strategy structured-data extraction. Tries JSON-LD (schema.org) → __NEXT_DATA__ → Nuxt → JSON-in-script (Magento, Shopify, BigCommerce custom-typed scripts) → OpenGraph/meta → microdata → text_main fallback, returns the highest-confidence hit as {strategy, confidence, data, tried}. Use this as the one-shot 'give me the data, you figure out how' call when you don't want to plan the strategy yourself. Pass strategy='json_ld' (or any of the names above) to force a specific extractor.

NameTypeReqDescription
strategystringOptional: force a specific extractor (json_ld, next_data, nuxt_data, json_in_script, og_meta, microdata, text_main)

No output schema declared.

No examples provided.

extract_cards ~146

Auto-detect repeated article/card/product/course/listing blocks and return normalized items [{title, price, condition, url, availability, snippet, meta, image_alt, score}]. Prefer this over extract_list when the page has semantically ambiguous recipe, course, product, or model cards and you do not already know field selectors. Optional selector scopes detection to known card nodes; kind can bias scoring (recipe, course, product, listing).

NameTypeReqDescription
kindstringOptional hint: recipe, course, product, listing, article
limitintegerMax items to extract (default 50)
selectorstringOptional CSS selector matching each card/listing block

No output schema declared.

No examples provided.

extract_list ~148

Pull a repeated card pattern into [{...}, {...}]. Right tool for HN-style lists, search results, product grids — collapses per-site eval boilerplate. Field spec shapes: 'css selector' (text content), 'css selector @attr' (attribute), or ['css selector', '@attr'] (tuple form). If a sub-selector returns null, the field value is null.

NameTypeReqDescription
fieldsobjectyes{field_name: 'sub-selector' | 'sub-selector @attr' | ['sub-selector', '@attr']}
item_selectorstringyesCSS selector matching each card/row
limitintegerMax items to extract (default 1000)

No output schema declared.

No examples provided.

extract_table ~116

Pull a <table> into {headers, rows, row_count}. Headers come from <thead><th>...</th></thead> if present, else the first <tr>'s <th> cells. Each subsequent <tr>'s <td> cells become a row dict keyed by header (or 'col_N' if no header for that column). Right tool for pricing tables, specs, finance/listings tables — saves writing the per-cell mapping eval.

NameTypeReqDescription
selectorstringyesCSS selector matching the <table> element

No output schema declared.

No examples provided.

find_text ~128

Find localized text matches and return [{ref, tag, attrs, before, match, after, text}]. Ranks article/main/content matches above nav/header/footer boilerplate.

NameTypeReqDescription
context_charsintegerCharacters before/after each match (default 80)
exactbooleanIf true, exact cleaned-text match instead of substring (default false)
limitintegerMax matches to return (default 20)
selectorstringOptional CSS selector to limit search scope
textstringyesSubstring to match (or exact string if exact=true)

No output schema declared.

No examples provided.

help ~97

Discover full tooling from the minimal 3. Returns grouped catalog of all 32 tools with when to use and example. Minimal profile shows only navigate (as open), extract, help; help unlocks the rest. Use help(topic) to filter e.g. 'query', 'extraction', 'discovery'.

NameTypeReqDescription
topicstringOptional topic filter: query, reading, discovery, extraction, interaction, session, or a tool name

No output schema declared.

No examples provided.

navigate ~566

Fetch a URL with Chrome-fingerprinted HTTP using the active profile. Parses HTML, seeds the JS DOM, returns BlockMap inline. With `exec_scripts: true`, extracts inline AND external <script> tags from the parsed HTML, fetches externals in parallel (8s per-fetch timeout), eval's them in document order in QuickJS (with shims for setTimeout/fetch/etc.), then settles the event loop and fires DOMContentLoaded + load. `<script async>` is honored: async scripts execute after the sync queue. When `--policy=blocklist` is set, tracker URLs are blocked at script-fetch time (see scripts.policy_blocked in the result). Returns a `scripts` summary with inline_count, external_count, async_count, policy_blocked, executed, errors. Auto-extract: when the page embeds JSON-bearing <script> tags (density.json_scripts > 0 — covers application/json, application/ld+json, text/x-magento-init, text/x-shopify-app, etc.), navigate auto-runs `extract()` and returns the result as the `extract` field. Saves a round trip on the common case where the data the JS would have rendered is already sitting in the HTML — JSON-LD article schemas on news sites, __NEXT_DATA__ page state on Next.js apps, json_in_script product blobs on Magento/Shopify, GitHub RSC payloads, etc. Capped at 16 KB inline; over that limit `extract` returns a stub with strategy/confidence/size_bytes/hint and the agent should call `extract()` explicitly to retrieve the full payload. Pages with no embedded JSON get extract:null and pay zero extra cost. Tool advice: navigate also returns `tool_likelihoods` plus `tool_recommendations`, derived from concrete page signals (structure/headings, selector hints, density, embedded data, network captures, challenge state, and script pathology) so agents can pick the next tool without guessing. Auto-solve: Reddit's JS proof-of-work challenge (provider: reddit_js_challenge) is transparently solved — the challenge is detected, the GET solution URL is computed (solution = hex_value + hex_value),…

NameTypeReqDescription
exec_scriptsbooleanRun page <script> tags (inline + external src) after parse, settle the event loop, and fire DOMContentLoaded + load. Default false.
include_asciibooleanInclude human-readable ASCII blockmap grid (redundant with JSON fields). Default false.
urlstringyesAbsolute URL to fetch

No output schema declared.

No examples provided.

network_extract ~154

Parse captured JSON/API/network responses into semantic objects with fields, scores, matched query terms, and capture/path provenance. Use after navigate or activate when network_stores shows JSON/GraphQL/NDJSON captures and raw body_preview is too noisy.

NameTypeReqDescription
hoststringOptional substring filter on response host.
limitintegerMax objects to return (default 50).
nav_idstringDefaults to the most recent navigation_id. Pass 'all' to inspect all captures.
querystringOptional task query/goal used to rank objects.
typesarrayOptional object kinds to keep, e.g. product_card, article_card, model_card, network_object, card.

No output schema declared.

No examples provided.

network_stores ~238

Return content-bearing fetch/XHR responses captured during navigate, ranked by likely content value. SPAs often keep their data in API responses (JSON, GraphQL, NDJSON, Next/Nuxt route data) that are cleaner than the rendered DOM — this tool surfaces them directly. Each entry has capture_id, URL, status, content-type, body_preview (truncated to 256 KB), body_bytes (full size), body_truncated flag, navigation_id, and a heuristic score. Bodies for trackers/ads/CSS/HTML/media are NOT captured. The navigate result already contains a top-5 summary scoped to that navigation; use this tool to get more entries, filter by host, or pull captures from a different navigation.

NameTypeReqDescription
hoststringOptional substring filter on response host.
limitintegerMax entries to return (default 20).
nav_idstringDefaults to the most recent navigation_id (page B never sees page A captures). Pass an explicit navigation_id from a prior navigate result to query that navigation specifically. Pass 'all' to disable…

No output schema declared.

No examples provided.

network_stores_clear ~43

Drop all captured network responses from the session's network store. Use this between unrelated navigations if you don't want earlier captures showing up in later network_stores calls.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

page_model ~150

Render the current page into semantic, task-discoverable JSON objects. Reconstructs page structure as search_form, nav_link, article_card, course_card, model_card, product_card, table, answer_block, and limitation objects with actions, normalized fields, goal-based scoring, and provenance. Prefer this as the first planning tool after navigate when raw links/text are too wide.

NameTypeReqDescription
goalstringOptional task goal/query used to rank objects by relevance.
limitintegerMax objects to return (default 50).
typesarrayOptional object kinds to return, e.g. search_form, article_card, model_card, course_card, card, table, answer_block.

No output schema declared.

No examples provided.

query ~141

Run a CSS selector against the current page's parsed DOM. Returns matching elements as [{ref, tag, attrs, text, text_chars, text_truncated}]. Element refs (e:NN) are stable handles for use with click/type/submit. Selector engine supports tag, id, class, attribute matchers (=, ^=, $=, *=, ~=), all four combinators (descendant, >, +, ~), pseudo-classes (:first/last/nth-child including An+B formulas, :first/last/nth-of-type, :only-child/of-type), :not(), and :has().

NameTypeReqDescription
selectorstringyesCSS selector

No output schema declared.

No examples provided.

query_debug ~110

Diagnose why a CSS selector did or did not match. Returns matched_count, sample matches, DOM summary counts, selector hints (top tags/classes/data attrs/ids), and actionable hints for selector_miss, thin_shell, or embedded_json. Use this when query() returns [] and you need to distinguish a bad selector from an empty/browser-rendered DOM.

NameTypeReqDescription
limitintegerMax sample matches to return (default 10, max 50)
selectorstringyesCSS selector to test

No output schema declared.

No examples provided.

query_text ~178

Find elements by visible text content. Returns the smallest/deepest element whose textContent matches the needle, with chrome (header/nav/footer/aside) skipped. Anchor-promotion: a span/strong/etc. inside an <a> resolves to the anchor (so click() targets the actionable element). Right tool when CSS selectors are unstable (React-rendered pages with hashed class names) but the visible label is reliable — e.g. find a 'Sign in' button without knowing its class.

NameTypeReqDescription
exactbooleanIf true, exact match instead of substring (default false)
limitintegerMax matches to return (default 20)
selectorstringOptional CSS selector to limit search scope (default: whole document body)
textstringyesSubstring to match (or exact string if exact=true)

No output schema declared.

No examples provided.

report_outcome ~220

Bind a task outcome (success/failure/quality) to a previous navigation_id from a navigate() call. Used by the policy framework's outcome protocol — see docs/probabilistic-policy.md §4.5. v0 emits an outcome_reported NDJSON event for the navigation; no posterior updates yet. Drivers should call this once per agent task so future Bayesian phases (B/D-2) can attribute extraction success/failure to specific policy decisions.

NameTypeReqDescription
errorstringOptional human-readable error/explanation when success=false.
navigation_idstringyesThe id returned by navigate() — joins this outcome to the policy_trace event.
qualitynumberOptional 0..1 quality score (e.g. fraction of expected fields extracted).
successbooleanyesDid the agent's task succeed?
task_classstringWhat kind of task succeeded/failed. Lets future posteriors condition on task class.
task_idstringOptional opaque id chosen by the driver for cross-system correlation.

No output schema declared.

No examples provided.

route_discover ~88

Find page-owned navigation/search routes for a goal. Returns ranked visible links, forms with controls/query_url previews, and inferred URLs derived from page-owned routes plus goal terms. Use before guessing URLs manually.

NameTypeReqDescription
goalstringOptional task goal/query used to rank routes and build GET query previews.
limitintegerMax routes/forms/inferred URLs per section (default 30).

No output schema declared.

No examples provided.

settle ~131

Drain the JS event loop: alternately runs queued microtasks (Promise resolutions) and fires expired setTimeout/setInterval callbacks, sleeping to the next deadline when only timers remain. Returns when the queue is empty OR max_ms elapses OR max_iters iterations complete. Defaults: max_ms=2000, max_iters=50. Use after seeding the DOM (or after eval'd code that schedules timers) to let pending callbacks run.

NameTypeReqDescription
max_itersintegerMax iterations of the drain loop (default 50)
max_msintegerMax wall-clock ms to spend (default 2000)

No output schema declared.

No examples provided.

submit ~64

Submit a form by gathering input/textarea/select values and navigating to the resolved action URL. Supports GET and application/x-www-form-urlencoded POST. Checked checkbox/radio values are serialized; multipart upload forms are not supported.

NameTypeReqDescription
refstringyesForm element ref like e:142

No output schema declared.

No examples provided.

table_to_json ~72

Alias for extract_table with a first-table default. Pulls a table into {headers, rows, row_count}; selector defaults to 'table'. Use this when an agent expects a table-to-JSON convenience tool.

NameTypeReqDescription
selectorstringOptional CSS selector matching the <table> element (default: table)

No output schema declared.

No examples provided.

text ~78

Get the textContent of the FIRST element matching the selector (default: body). Note: on Wikipedia/MDN/news sites, the first <p> is often a hatnote or image caption, not the lead paragraph — prefer `text_main` for reading the page's primary content.

NameTypeReqDescription
selectorstringCSS selector (default: body)

No output schema declared.

No examples provided.

text_around ~96

Return cleaned surrounding text around an element ref or the best ranked text match. Returns {ref, before, match, after, text}.

NameTypeReqDescription
context_charsintegerCharacters before/after the target (default 400)
refstringOptional element ref like e:142
selectorstringOptional CSS selector to scope context
textstringOptional text to locate when ref is omitted

No output schema declared.

No examples provided.

text_clean ~89

Return chrome-stripped, JSON-stripped, whitespace-collapsed text from a selector or the best content root. Drops script/style/noscript/svg and page chrome (nav/header/footer/aside) plus obvious hidden widgets and repeated boilerplate.

NameTypeReqDescription
max_charsintegerOptional max characters to return.
selectorstringOptional CSS selector to scope extraction. Default: best content root.

No output schema declared.

No examples provided.

text_main ~71

Get the textContent of the page's main content area, excluding chrome (header/nav/footer/aside). Tries <main>, then [role=main], then a single <article>, then falls back to the longest non-chrome subtree. Use this for reading article body / docs page / blog post content.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

type ~60

Set the value of an input/textarea (referenced by `ref`) and dispatch input + change events. Use before submit on form fields.

NameTypeReqDescription
refstringyesInput element ref like e:142
textstringyesValue to set

No output schema declared.

No examples provided.

Common questions

What is the unbrowser by Unchained MCP server?

unbrowser by Unchained is an MCP server listed in the public MCP registry as io.github.protostatis/unbrowser. Chrome-free MCP web access for agents with low-token page maps and browser escalation hints. This page covers its PyPI package (pyunbrowser).

Is the unbrowser by Unchained MCP server safe to use?

unbrowser by Unchained scores 65 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 20 September 2026. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

What tools does the unbrowser by Unchained MCP server expose?

unbrowser by Unchained exposes 33 tools: navigate, query, query_debug, text, text_main, and 28 more. Their descriptions and schemas cost roughly 4,113 tokens of context every time the server is loaded.

Is the unbrowser by Unchained MCP server still maintained?

unbrowser by Unchained is still listed as active in the MCP registry. We last reached this channel on 20 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

What licence is the unbrowser by Unchained MCP server under?

unbrowser by Unchained declares the Apache-2.0 licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.