nokk
Automatically clears Cloudflare challenges (Turnstile invisible widgets, managed interstitials, and the interactive 'Verify you are human' checkbox) while browsing, thanks to a Chrome-matching TLS/HTTP and JavaScript fingerprint. Options control the time budget for solving, whether to stop as soon as a cf_clearance cookie is obtained, and whether to auto-solve on every navigation over CDP.
A stealth headless browser engine in Rust. Passes Cloudflare without Chromium.
Real V8 and a DOM, a Chrome TLS/HTTP fingerprint (JA3/JA4) and JS-level stealth, driven over the Chrome DevTools Protocol: Puppeteer and Playwright connect as usual. Also an MCP server for AI agents.
scrapingcourse.com's Cloudflare test page, one run from a home connection; medians across sites are in the tables below.
The nøkk is a shapeshifting water-spirit of Norse myth that takes on a familiar shape to pass unnoticed. This one takes the shape of Chrome.
Install
pip install nokk # Python: the prebuilt binary is in the wheel
npm install @koloss777/nokk # Node: run it with `npx nokk`
docker run --rm -p 9222:9222 ghcr.io/koloss777/nokk:latestNo browser to download. Prebuilt for Linux (x86_64, ARM64), macOS on Apple Silicon and Windows x64; anything else builds from source.
Related MCP server: Airbrowser
Quick start
# Load a page behind Cloudflare, clear the challenge, print what is behind it
nokk --load https://www.scrapingcourse.com/cloudflare-challenge --solve-challenge 30 \
--eval "document.querySelector('h2').textContent.trim()"
# Or run the CDP server and drive it from any client
nokk --port 9222 --auto-solve # ws://127.0.0.1:9222/devtools/browser/nokkimport nokk
from playwright.sync_api import sync_playwright
with nokk.launch(auto_solve=True) as server, sync_playwright() as pw:
page = pw.chromium.connect_over_cdp(server.ws_endpoint).new_page()
page.goto("https://www.scrapingcourse.com/cloudflare-challenge")
print(page.title())For AI agents, uvx nokk-mcp runs it as an MCP server.
Puppeteer, Node, sessions and the Cloudflare options are below.
Why nokk
Puppeteer and Playwright drive a real Chromium, and anti-bot systems spot it through
navigator.webdriver, CDP artifacts and a headless TLS handshake. nokk is built to
look like Chrome from the TLS handshake to the JavaScript environment, and has no
rendering engine at all.
nokk 0.1.35 | Chrome 151 (Puppeteer / Playwright) | |
Start until CDP answers | ~0.05 s | ~0.2 s |
Idle memory (PSS) | ~60 MB, 1 process | ~330 MB, 12–14 processes |
Cloudflare solve, median wall time | 12.4 s | 12.4 s |
Slowest solve | 15.6 s | 27.8 s |
CPU per solve | 6.4 s | 9.5 s |
Peak memory per solve | ~570 MB | ~720 MB |
Solved | 24/24 | 24/24 |
TLS fingerprint (JA3/JA4) | matches Chrome 151 | Chrome |
Screenshots, PDF, layout | no | yes |
CDP coverage | the common path | full |
Measured on nokk 0.1.35, an 8-core Linux box, October 2026. Cloudflare row: 8 production sites × 3 runs through one proxy, nokk with --until-clearance, Chrome driven by a checkbox-clicking harness; a solve counts only if the site then opens with the cookie.
Not for you if you need screenshots, PDFs, layout or paint, or the whole Playwright/CDP surface: nokk has no rendering engine by design, and its CDP coverage is the path Puppeteer and Playwright use for navigation and scripting.
Measured on public pages
Three runs per page from the CLI with --solve-challenge 30 and no proxy, on an 8-core
Linux box (October 2026). The time is the whole command, from process start to the printed
result. Run them yourself with tools/cf-check.sh.
Page | Challenge | Solved | Median | Slowest |
| invisible Turnstile widget on a live site | 3/3 | 7 s | 9 s |
| managed interstitial | 3/3 | 5 s | 7 s |
| managed widget | 3/3 | 7 s | 8 s |
| non-interactive widget | 3/3 | 3 s | 4 s |
| interactive interstitial with a checkbox | 3/3 | 10 s | 11 s |
On production sites behind Cloudflare the result is in the comparison above: 8 sites, 24 of 24 solved. Those sites are not named here.
Usage
Command line
nokk --fetch https://tls.browserleaks.com/json # Chrome TLS + HTTP/2 fingerprint
nokk --load https://example.com --eval 'document.title' # run the page, query the DOM
nokk --load https://quotes.toscrape.com --dump-requests # every request the page makes
nokk --load https://target --proxy socks5://host:1080 # through a proxy
nokk --port 9222 --rotate-fingerprint --geoip-timezone # CDP server, a machine per contextAd, analytics and tracker requests are dropped by default; --allow-trackers loads them.
Anti-bot vendors are never blocked, because they must run to hand out a token.
Puppeteer
import puppeteer from 'puppeteer';
const browser = await puppeteer.connect({
browserWSEndpoint: 'ws://127.0.0.1:9222/devtools/browser/nokk', // nokk --port 9222
});
const page = await browser.newPage();
await page.goto('https://example.com');
console.log(await page.title());Node and Python
Both packages carry the prebuilt binary and start the CDP server for you.
const server = await require("@koloss777/nokk").launch({ autoSolve: true });
// server.wsEndpoint -> puppeteer.connect / chromium.connectOverCDPwith nokk.launch(auto_solve=True) as server: # or: await nokk.launch_async()
... # server.ws_endpoint -> connect_over_cdpcrawl4ai, Scrapy, Playwright MCP and other CDP tools
Anything that drives Chrome over CDP can drive nokk instead. crawl4ai, stopped by
Cloudflare with its own Chromium, gets the page behind it through nokk:
BrowserConfig(browser_mode="custom", cdp_url=server.ws_endpoint). Scrapy
(scrapy-playwright's PLAYWRIGHT_CDP_URL) and Playwright MCP (--cdp-endpoint)
work the same way. See docs/integrations.md.
For AI agents (MCP)
nokk runs as a Model Context Protocol server, so an agent such as Claude Desktop or Claude Code browses through the fingerprinted engine. With uv nothing needs installing first:
{ "mcpServers": { "nokk": { "command": "uvx", "args": ["nokk-mcp", "--rotate-fingerprint"] } } }Without uv: pip install "nokk[mcp]", then "command": "python", "args": ["-m", "nokk.mcp"].
Tools: open, read_text, read_html, click, fill, evaluate, links, solve_challenge,
challenge_state, reset.
Cloudflare challenges
nokk clears Turnstile by itself: the invisible widget, the managed interstitial and the interactive Verify you are human checkbox. Nothing is configured per site. Where a widget needs a press, the engine presses it like a person would.
--solve-challenge Nsets the time budget, and--fail-on-challengeexits3if a gate is still up.--until-clearancestops at a freshcf_clearanceand skips the heavy page behind the gate.--auto-solvedoes the same for everypage.goto()over CDP;Nokk.solveChallengedoes it on demand.A
cf_clearancefrom a real browser can be imported, because nokk's JA4 matches Chrome 151.
Details, the CDP methods and events: docs/cloudflare.md.
Persistent sessions
--session-store ./sessions saves each named session's cookie jar, cf_clearance included,
to disk and reloads it in a new process. Warm a session once and reuse it instead of
solving the challenge on every run. See docs/sessions.md.
Rotating fingerprints
--rotate-fingerprint gives every browser context its own coherent machine: TLS emulation,
User-Agent, client hints, platform, screen and WebGL all agree. --geoip-timezone matches the
timezone and languages to the proxy's exit IP. See docs/fingerprints.md.
Builds
Build | What it adds | Where |
light (default) | everything above; canvas and WebGL pixels are synthesised | pip, npm, |
render | real canvas 2D and WebGL rasterisation, about 100 MB more at peak |
|
Prebuilt for Linux x86_64 and ARM64, macOS on Apple Silicon and Windows x64; the render build for Linux x86_64. Docker variants, the archives and building from source are in docs/install.md.
How it works
A Cargo workspace of small crates: a V8 isolate pool, a Chrome-fingerprinted HTTP client on
BoringSSL, an html5ever DOM, the stealth layer and a CDP server. Concurrency is one isolate
per thread with many contexts each, all IO runs on tokio off the isolate threads, and the
JS fingerprint and the TLS fingerprint always agree. More in docs/architecture.md.
Project status
Alpha. The engine is real and end-to-end: V8 executes page JS against a parsed DOM, the fingerprinted transport clears Cloudflare's TLS/HTTP checks, the engine solves Turnstile on live sites — invisible, managed and interactive — and Puppeteer and Playwright connect over CDP to open a page, navigate, and evaluate.
What is not done yet, and where the sharp edges are:
JS-fingerprint hardening is ongoing. Much of the hardening is in place — native
toStringmasking, internals hidden fromObject.getOwnPropertyNames,navigator/screenas real prototype instances, an IP-coherent timezone, and per-context coherent fingerprint rotation, Web Workers, canvas/WebGL/WebGPU/audio with Chrome's pixels and samples, Trusted Types and CSP. nokk solves Cloudflare's challenges today, and the comparison against Chrome section by section is how the remaining tells get found; it is not yet a match for a dedicated fingerprinting suite like CreepJS. See the roadmap.CDP coverage is the common path, not the whole protocol. Puppeteer and Playwright connect over CDP: navigation,
evaluate,$/$eval/$$eval,title(),url(), new pages and CDP sessions are tested; less-common domains are not implemented yet.Per-context cookie isolation and per-session persistence work (each browser context gets its own jar; named sessions persist across runs); per-host / per-proxy / global connection limits are not yet enforced (Phase 7).
No rendering — screenshots, PDF, and layout/paint are out of scope by design.
See ROADMAP.md for the phased plan and the concrete hardening backlog.
Contributing
Issues and PRs are welcome — the hardening backlog in the roadmap is a good place to start. Before sending a change:
cargo fmt
cargo clippy --all-targets
cargo testLicense
Licensed under either of MIT or Apache-2.0 at your option.
Unless you explicitly state otherwise, any contribution you submit for inclusion in this work, as defined in the Apache-2.0 license, shall be dual-licensed as above, without any additional terms or conditions.
Available Tools
10 toolschallenge_stateA
Which gate the current page shows: kind is "none",
"cloudflare-interstitial", "turnstile-widget", "aws-waf",
"recaptcha-widget" or "datadome" (recognised, not solvable);
solvable says whether solve_challenge can take it on.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It discloses the output fields and the notable behavior that datadome is recognised but not solvable, but it does not explicitly confirm the call is side-effect-free or safe to poll.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The single sentence is front-loaded with what the tool reports, then lists only the necessary enum values and the solvable linkage. No sentence is redundant for a state-query tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter state query with an output schema present, the description supplies the key enum meanings and the relationship to solve_challenge. An agent has enough context to call it and interpret the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are zero input parameters, so the baseline is 4. The description does not need to document parameter syntax, and it adds useful output-field semantics instead.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
It states exactly what is reported: the gate shown on the current page, with enumerated kind values. It also names solve_challenge and clarifies that solvable indicates whether solve_challenge can handle the gate, distinguishing this state check from the solving action.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The mention that solvable indicates whether solve_challenge can take it on implies this tool should be consulted before solving, but it does not explicitly say when to call it, when not to call it, or what to do for each gate kind. Usage is inferable rather than spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
clickC
Click the first element matching the CSS selector.
| Name | Required | Description | Default |
|---|---|---|---|
| selector | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden, yet it does not disclose whether clicking waits for the element, scrolls it into view, what happens if no element matches, or what side effects (e.g., navigation) may occur. It only notes that the first matching element is targeted, leaving critical interaction behavior unclear.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, front-loaded sentence that contains no wasted words. The action and targeting rule are conveyed immediately.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a browser-automation click tool with no annotations and an output schema, the description is missing key behavioral context: whether the click is synchronous, how failures are handled, and what preconditions exist. Output schema may cover return values, but the description is too sparse for the complexity of the action.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the schema itself provides no meaning beyond 'Selector: string'. The description compensates partially by clarifying that selector is a CSS selector and that the first matching element is clicked, but it adds no syntax details, examples, or constraints.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb (click) and target (first element matching the CSS selector), making the basic action clear. However, it does not differentiate this tool from siblings like fill or evaluate, which could also interact with elements.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit guidance on when to use click versus alternatives such as fill or evaluate, nor are there any stated prerequisites or exclusions. The agent must infer usage from the tool name and one-sentence description alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
evaluateC
Evaluate a JavaScript expression in the current page and return its value.
| Name | Required | Description | Default |
|---|---|---|---|
| expression | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden for an arbitrary-code-execution tool, yet it says nothing about side effects, whether the expression can mutate page state, whether it runs before or after page load, or how failures surface. It does at least anchor execution to 'the current page', which is minimal but useful context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, front-loaded with the action and ending with the return behavior; nothing is wasted. It is terse to the point of under-specification, but the structure itself is clean.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description should explain what 'its value' looks like when serialized (primitives vs. objects vs. DOM nodes) and how errors are returned. For a tool that executes arbitrary code, these omissions leave meaningful ambiguity for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% for the single 'expression' parameter, so the description must compensate; it does partially by clarifying the value is a JavaScript expression whose result is returned. It adds no information on whether statements, multi-line bodies, or async expressions are accepted.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Evaluate a JavaScript expression in the current page') with the effect ('return its value'), which is far more informative than the bare name. It does not explicitly contrast with read_text/read_html, which are the obvious alternatives for extracting page content, so it falls short of full sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to choose this over read_text, read_html, or links, nor any warning about when not to use it. The agent must infer that this is for computed extraction that the other read tools cannot express.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fillB
Set the value of the form field matching selector and fire input/change.
| Name | Required | Description | Default |
|---|---|---|---|
| value | Yes | ||
| selector | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It usefully discloses that input and change events are dispatched (important for framework-driven pages), but omits whether the existing value is replaced or appended, whether the element is scrolled into view, and how failures are reported.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One tight sentence with the operation front-loaded and no filler. The doubled backticks around selector are a minor formatting blemish but cost no comprehension.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained. However, with zero annotations and zero schema descriptions on a mutation-style DOM interaction, the description should say more about value replacement semantics and failure behavior to be fully sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% for both required parameters. The description only says the selector 'matches' a form field; it does not specify accepted selector syntax (CSS vs XPath) or clarify that value is a raw string assignment rather than e.g. key-by-key typing.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Set the value of the form field matching selector') plus a behavioral effect (fire input/change), which clearly separates it from siblings like click or read_text. It does not explicitly name an alternative, but the resource-level specificity is enough to identify the operation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this instead of click or evaluate, no prerequisites such as the element needing to be visible, enabled, or already focused, and no mention of what happens when the selector matches nothing or multiple elements.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linksB
All absolute hyperlink URLs on the current page.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry the behavioral load. 'Absolute' usefully signals that relative hrefs are resolved (or excluded) and 'current page' scopes it to the loaded document, but it never states whether hidden/duplicate links are included, whether order matches DOM order, or whether it triggers a navigation/fetch. The output schema covers the return shape, which lowers the burden.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single compact sentence with the key qualifier ('absolute') front-loaded and zero filler. It is a sentence fragment rather than a complete statement, which is the only structural weakness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter extractor with a full output schema, the description covers what the tool returns and its scope. The only meaningful gap is relative-link handling and ordering, which an agent would likely want before relying on the output.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate; baseline 4 applies. The description does correctly frame the implicit input as the currently loaded page.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names the resource precisely ('absolute hyperlink URLs on the current page'), which lets an agent distinguish it from read_html/read_text (full document content) or evaluate (arbitrary JS). It stops short of an explicit verb like 'List/Extract', so it reads as a noun phrase, but the intent is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to prefer this over read_html, read_text, or evaluate — all siblings that could also surface link data. The agent must infer that this is the lightweight link-only extraction path.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openA
Navigate the stealth browser to url. Returns the final {url, title}.
A Cloudflare challenge on the way is solved before this returns (unless the
server runs with --no-auto-solve); challenge then reports what was
met: kind, solved, and remaining ("none" when through).
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the behavioral burden, and it does disclose the non-obvious automatic Cloudflare challenge solving plus the `--no-auto-solve` exception. It also explains that `challenge` reports `kind`, `solved`, and `remaining`, though it omits timeout, error, and session/cookie effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The definition is two sentences, front-loaded with the navigation action and return shape, then adding the Cloudflare caveat. The parenthetical detail is purposeful and does not obscure the core operation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be fully explained, and the description adds important context about challenge handling. It is mostly complete for a one-parameter navigation tool, though explicit sibling usage guidance is still missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The only parameter is `url`, and schema description coverage is 0%, so the description must compensate for the missing documentation. It repeats `url` in context but adds no format details, validation rules, or absolute/relative URL semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: navigate the stealth browser to `url`, and it identifies the returned `{url, title}`. It does not explicitly distinguish this from sibling tools such as `solve_challenge`, `challenge_state`, or `read_html`, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies this is the navigation tool and notes automatic Cloudflare challenge solving unless `--no-auto-solve` is set. However, it does not say when to choose `open` versus siblings like `solve_challenge`, `challenge_state`, or `read_text`, leaving usage largely inferred.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_htmlA
Outer HTML of the current page, or of the first element matching the CSS
selector if given.
| Name | Required | Description | Default |
|---|---|---|---|
| selector | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations, so the description carries the full burden. It does disclose two useful behaviors: omitting the selector returns the whole page, and when a selector is given only the FIRST match is returned. It omits what happens on a non-matching selector (empty result vs. error), whether the call scopes to the top-level document or includes iframes/shadow DOM, and any size limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, front-loaded with the primary return value, with the conditional selector case appended. Nothing wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return shape needn't be described, and the description covers the main behavioral question (whole page vs. single matched element). The remaining gap is failure/miss semantics, which matters more here because there are no annotations to fall back on.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must supply meaning and it largely does: the sole parameter is a CSS selector, it is optional (default yields the full page), and only the first match is used. Missing only a concrete selector syntax example.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific resource and the exact thing returned: the outer HTML of the current page, or of the first element matching the CSS selector. This implicitly separates it from read_text (markup vs. text) without naming that sibling, so an agent can still route correctly but must infer the boundary.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: you'd reach for it when you need raw markup rather than extracted text. There is no explicit 'use this instead of read_text when...' guidance and no stated preconditions such as requiring an open page.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_textA
Visible text of the current page, or of the first element matching the CSS
selector if given.
| Name | Required | Description | Default |
|---|---|---|---|
| selector | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full behavioral burden. 'Visible text' usefully discloses that non-rendered content is skipped, but nothing is said about what happens when the selector matches nothing, whether it throws or returns empty, or whether any page navigation is triggered.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with the default behavior folded into a subordinate clause. Nothing redundant and nothing padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return shape need not be explained, and there is only one optional parameter. The remaining gap is a no-match / empty-result behavior, which matters for an agent deciding whether to fall back to read_html.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% (the selector param is an undescribed string with an empty default), so the description must compensate. It does so meaningfully: selector is a CSS selector, matching is first-element-only, and omitting it defaults to the whole page's text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('read_text') and scopes it: visible text of the current page, or of the first element matching a CSS selector. That contrasts implicitly with the sibling read_html (raw markup vs rendered text), though it never names the sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The word 'visible' implies rendered text extraction as opposed to markup, which nudges toward read_html for structure. But there is no explicit when-to-use statement, no exclusion (e.g., iframes, hidden elements), and no alternatives named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resetA
Discard the current browsing session (a fresh, coherent identity is used for the next navigation).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must carry the behavioral burden. It does disclose the key side effect (the session is discarded) and the post-condition (new identity on next navigation), but says nothing about what exactly is lost (cookies, storage, challenge state) or whether the reset affects in-flight state used by solve_challenge/challenge_state.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence with the action front-loaded and the consequence in a compact parenthetical. Every clause adds information; nothing is redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter reset with an output schema covering return values, the definition gives enough to call it correctly. The one gap is the interaction with sibling state tools (challenge_state, solve_challenge), which an agent might reasonably wonder about.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4; there is nothing for the description to disambiguate. It does not need to explain any inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('discard') and a specific resource ('the current browsing session'), plus the resulting state ('a fresh, coherent identity is used for the next navigation'). That is clear enough to separate it from open/click/fill, though it never names a sibling to contrast against.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The parenthetical implies the reason to call it (you want a clean identity before the next navigation), but there is no explicit when-to-use / when-not-to-use statement or reference to alternatives such as opening a new page or clearing challenge state. Usage is inferable rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
solve_challengeA
Solve the Cloudflare challenge the current page shows — the "Just a
moment…" interstitial or a Turnstile widget — pressing its checkbox if it
puts one up. Returns status, solved, remaining, title, url.
| Name | Required | Description | Default |
|---|---|---|---|
| timeout_seconds | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does explain the interaction (checkbox press if offered) and lists returned fields. It omits key behavior: whether it blocks/polls until solved, what happens when it times out, and whether it is safe to re-invoke.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with the action front-loaded and the return fields enumerated at the end. Little waste, though the return-value list partly duplicates the existing output schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The output schema already documents the return shape, so listing status/solved/remaining/title/url is redundant but harmless. For a no-annotation, no-required-param tool the remaining gap is failure/timeout behavior, which is a moderate rather than fatal omission.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single optional timeout_seconds parameter has a self-explanatory name and a schema default, but schema coverage is 0% and the description says nothing about it — notably what happens when the timeout is exceeded, despite 'remaining' hinting at a waiting loop.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific action and target: solving the Cloudflare interstitial or Turnstile widget by pressing its checkbox. It is clearly distinct from read_text/click/fill, but it never mentions the sibling challenge_state, which is the obvious diagnostic counterpart.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implicitly scoped to 'the current page' showing a challenge, but there is no guidance on when to call it versus challenge_state, nor what to do if no challenge is present or if it recurs after solving.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
10 tool updates
v0.1.46- First observed
challenge_state - First observed
click - First observed
evaluate - First observed
fill - First observed
links - First observed
open - First observed
read_html - First observed
read_text - First observed
reset - First observed
solve_challenge
TDQS
Scored across 10 tools
Each tool maps to a distinct action on the browser session: navigate (open), interact (click/fill), read (read_text/read_html/links), execute JS (evaluate), and Cloudflare handling (solve_challenge vs challenge_state, one acting and one querying). The only mild overlap is that `open` can auto-solve challenges while `solve_challenge` does so manually, but the description explicitly flags this and reports the challenge outcome, so an agent can tell them apart.
Names are uniformly short, lowercase snake_case, with related tools grouped by prefix (read_text/read_html, challenge_state/solve_challenge). Some tools are bare verbs (open, click, fill, evaluate) and one is a bare noun (links), so it is not a strict verb_noun pattern throughout, but the convention is predictable and readable.
Ten tools is well-scoped for a stealth browser driver: navigation, two readers, two interaction primitives, JS evaluation, link extraction, challenge state/solve, and session reset. Nothing looks redundant or padded.
The core browse-inspect-interact lifecycle plus Cloudflare bypass and session reset is covered, but there is no wait-for-element, screenshot, keyboard press/Enter, select-option, or history navigation tool. Most of these gaps are workaroundable via `evaluate` and `click`/`fill`, so they are minor rather than blocking.
Maintenance
Related MCP Connectors
Undetectable cloud browser sessions for AI agents and scrapers. Navigate, extract, click, captcha.
Browser agents and stealth cloud browsers for AI: run web tasks, fill forms, extract data.
Cloud browsers for AI agents: get past bot detection, sign in with MFA, run web tasks at scale.
Hosted browser for AI agents: screenshots, post-JS DOM, console, WCAG. No install, no API key.
Related MCP Servers
- AlicenseAqualityNot gradedmaintenanceEnables browser automation through Playwright using accessibility tree snapshots instead of screenshots. Supports web scraping, form interactions, testing, and connecting to existing browser sessions with logged-in accounts.233,369 npm5-
- AlicenseAqualityCmaintenanceOpen-source browser automation API with anti-detection for AI agents, web scraping, and automation, providing undetectable Chrome via MCP and REST API with Cloudflare bypass.2410MIT
- AlicenseBqualityAmaintenanceCloakBrowser MCP server for AI agents: Playwright-powered browsing, clean tool forwarding, Docker support, and multi-session HTTP transport.25826 npm172MIT
- AlicenseAqualityDmaintenanceStealth browser automation for AI agents, using source-patched Chromium to bypass bot detection systems like Cloudflare, reCAPTCHA, and FingerprintJS.28Apache 2.0