FrankenSurf
Uses Brave Search as one of the paid search sources in the search fallback chain (allowed only when paid tools are enabled), with every result checked for topic, page type and date window.
Exposes Frankensurf's page reading and search capabilities as CrewAI tools via frankensurf.agent_tools.crewai_tools.
Exposes Frankensurf's web reading and search capabilities as LangChain tools (frankensurf_read, frankensurf_search) via frankensurf.agent_tools.langchain_tools.
Provides Frankensurf's web reading and search capabilities as tools for the OpenAI Agents SDK via frankensurf.agent_tools.openai_agents_tools.
Runs a local SearXNG search engine (without Docker) as the free search source, used to strengthen the free search tier.
Uses Zyte as a paid page-reading fallback in the cheapest-first tool chain, for sites that block the free readers.
Every web tool breaks somewhere, and they break on different sites. Frankensurf sits in front of all of them and gives your agent one call. It tries the cheapest tool first, checks the page is real, moves to a stronger tool only when a site pushes back, and returns clean page data with a receipt of how it got there.
Quick start
Python 3.12+, on Linux, macOS, or Windows through WSL. No account or key needed.
pip install "frankensurf[mcp]"
frankensurf install # every free tool: browsers, stealth browsers, local search, Crawl4AI
frankensurf read "https://www.walmart.com/search?q=air+fryer" --explainThe read climbs until it gets the real page:
https://www.walmart.com/search?q=air+fryer
✗ http CAPTCHA 0.4s
✗ local CAPTCHA 1.5s
✓ camoufox got the page 15.6s
air fryer - Walmart.com
24,192 characters via camoufox, complete (107 results), freefrankensurf install works like playwright install: name just the tools you want
(frankensurf install search chromium), add --with-deps for the browsers' system libraries on
Linux, --list to see what's installed where, and frankensurf uninstall all to remove it. No
Docker needed. Each release is installed from PyPI on fresh Ubuntu and macOS machines and checked.
Related MCP server: Deep Research MCP Server
Use it
From an agent, as an MCP server (setup for each client):
claude mcp add frankensurf -- frankensurf-mcpFrom Python:
import frankensurf as fs
page = fs.read("https://example.com/pricing")
if page.ok:
print(page.title, page.text[:500])
else:
print("couldn't read it:", page.failure) # {"code": "CAPTCHA", "message": ...}
pages = fs.batch(urls, links=True) # paced per site, in order
hits = fs.search("playwright python tutorial", recency="month")
page = await fs.aread(url) # aread, abatch, asearch inside async codeFor a long-running service, keep one Runtime open: async with Runtime() as web: await web.read(url).
Map and crawl: fs.map(url) lists a site's URLs; fs.crawl(url, limit=50) reads a section of it as markdown.
Agent mode (pip install "frankensurf[agent]", any LiteLLM model): fs.ask("question") searches, reads and
answers with sources, and says what it couldn't read; fs.extract(urls, schema=...) and fs.summarize(url).
Agent mode.
In Docker, one install for your whole network: docker run -p 3002:3002 -e FRANKENSURF_API_KEY=... ghcr.io/yail259/frankensurf
(Docker).
From any tool that takes a Firecrawl URL (GPT Researcher, deep-research and others):
frankensurf serve, then point it at http://127.0.0.1:3002 (setup).
From the command line:
frankensurf read https://example.com --markdown
frankensurf search playwright python tutorial --recency week
frankensurf watch https://news.ycombinator.com/ --link-pattern 'item\?id=\d+'In Claude Code as a plugin (the MCP server plus the skill that teaches Claude to use it):
/plugin marketplace add yail259/frankensurf
/plugin install frankensurf@frankensurfFrom LangChain, the OpenAI Agents SDK or CrewAI (pip install "frankensurf[langchain]", and so on):
from frankensurf.agent_tools import langchain_tools # or openai_agents_tools, crewai_tools
tools = langchain_tools() # frankensurf_read, frankensurf_searchYou get raw page data, not answers: text or markdown, JSON-LD, the page's own JSON, images, and
the receipt. Your agent decides what the page means. If it isn't what it wanted, it asks again with
retry_of=<trace_id> and Frankensurf skips every tool it already tried.
Benchmark
Cost per 1,000 correct pages: Frankensurf's free tools $0 in fees, about $0.01 of a $5/month server (87–88% right); with paid fallbacks $0.22 (96%); Firecrawl on its own $0.71 on its Scale plan, $0.98 on Standard (85%). How that's worked out.
scripts/toolbench.py runs each tool on its own, then Frankensurf, on the same pages with the same
content checks. The newest set: 150 sites in 15 categories, picked before any was read, read once
(11 October 2026, raw rows in benchmarks/2026-10-11/).
Tool | Sites read | Median | Cost per 1k |
Plain HTTP only | 48.7% | 1.2 s | free |
Camoufox only | 68.7% | 10.9 s | free |
Jina Reader only | 73.3% | 1.5 s | free |
Firecrawl only | 84.7% | 4.6 s | $4.28 |
Zyte only | 86.0% | 10.7 s | not reported |
Frankensurf, free tools only | 88.0% | 3.6 s | $0 |
Frankensurf, with paid fallbacks | 96.0% | 2.9 s | $0.98 |
Frankensurf read 17 sites Firecrawl missed; Firecrawl read none it missed.
With no paid tools at all it is level with the best paid tool on its own (88.0% against 86.0% and 84.7%; at 150 sites that gap is within the noise).
Its slowest reads are slower: the slowest tenth takes 25.7 s against Firecrawl's 10.6 s, when a read climbs several tools.
Not a one-off: 95.3% vs 85.3% on the set the day before; 89.5% vs 80.3% and 88.5% vs 74.1% on earlier fresh sets.
Tool | Sites read | Median | Cost per 1k |
Patchright only | 38.7% | 4.1 s | free |
Headless Chromium only | 40.7% | 2.7 s | free |
Plain HTTP only | 48.7% | 1.2 s | free |
Camoufox only | 68.7% | 10.9 s | free |
Scrapling only | 68.7% | 8.5 s | free |
Jina Reader only | 73.3% | 1.5 s | free |
Firecrawl only | 84.7% | 4.6 s | $4.28 |
Zyte only | 86.0% | 10.7 s | not reported |
Frankensurf, free tools only | 88.0% | 3.6 s | $0 |
Frankensurf, with paid fallbacks | 96.0% | 2.9 s | $0.98 |
Medians are over pages read; cost is per 1,000 pages read right. ZenRows and Scrapfly are left out (their plans ran out of credits). From a fresh cloud VM, whose data-centre address sites wall more often: free tools 82.0%, lightning mode 84.0% at a 1.2 s median. See Benchmarks.
Search
search uses free sources first and checks every result: on topic, the right kind of page, inside
the date window. Exa, Brave, Tavily, Serper and other paid sources join only when you allow paid
tools. Judged blind (results pooled and shuffled, which tool found them hidden), useful results in
the top five:
Blind set 7 (120 queries) | Useful results (of 5) | Cost per 1k |
Frankensurf, paid allowed | 4.67 | $9.38 |
Exa only | 4.66 | $9.50 |
Frankensurf, free (with the local search engine) | 3.83 | $0 |
Free, it beats Firecrawl's search: better on 35 queries, worse on 5. With paid allowed it is level
with Exa. The local search engine (frankensurf install search, SearXNG without Docker) makes the
free tier much stronger. v0.41 improved free search again: on a fresh blind set of 120
queries it beat v0.40 on 41 and lost on 12 (3.42 against 2.71 useful results of 5,
benchmarks/2026-10-14-search-v041/). Details in
benchmarks/2026-10-13-search/.
What else is in the box
Every read carries
receipt.quality:good,partialorpoor, with flags such aspaywall,menusorplaceholder, so an agent knows when a page didn't really come through.--schema product.json(MCPschema) fills a JSON Schema from the page's JSON-LD, microdata, meta tags and own JSON intoextracted, and climbs to a stronger tool while a required field is missing (Structured fields).--main(MCPmain_content=True) addsmain_text: the article without menus, footers and banners (best withpip install "frankensurf[main]").A read with no page after 3 seconds starts two more free tools beside it and keeps the first complete page (
--lightningraces from the start).A URL that answers "not found" is looked up with the site's own search;
receipt.rescuedsays so.Still walled? Allow a real Chrome on your machine (
--real-browser, with its own profile, never yours) or a second connection (FRANKENSURF_EGRESS).
--site,--exclude-domain,--recencyand--regionon every source, and a--vertical(news, reference, discussions, qa, code, papers, books) backed by official free APIs.Monitoring-style queries (
"Acme" OR "Acme Corp" (acquisition OR layoffs)) are judged by the name they're about, and a weak answer is retried once with just the name.--mode mergeasks every source at once and fuses the results.frankensurf search-engine start|stop|statusmanages the local SearXNG; search restarts it after a reboot.
A bundled skill teaches agents the tools: the MCP server sends it as its instructions, and
frankensurf skill installadds it to~/.claude/skills.Profiles: log in once and any tool can use the session; the model never sees cookies or keys.
Human handoff: for a CAPTCHA or 2FA only a person can clear, it opens the page for you, then carries on.
Site modules: save what your agent learns about a site as data.
frankensurf module discover URL --query "desk lamp" --savefinds the site's search, reads the results and saves a module; after that, searches on that site come back as structureditems.Shared site knowledge:
frankensurf share syncstarts from which tool reads which site, as the community learned it;share exportwrites yours to review and contribute (opt in both ways).frankensurf watch-sites URL… --since DATElists new pages from the feeds and sitemaps sites publish.
Everything works with no keys. Paid tools are opt-in and only come in once a site has walled a free
tool, cheapest likely success first. Set their keys (for example FIRECRAWL_API_KEY) and pass
--paid; --max-cost USD caps a read. From Python: allow_paid_fallbacks and max_cost_usd.
See Paid tools and budgets.
How it works
Every way to fetch a page is a rung: plain HTTP and markdown negotiation, browsers, stealth browsers and signed requests, hosted browsers, paid APIs, and finally a person clearing the wall in a visible browser. A read starts at the cheapest rung and climbs only when a page pushes back. Every tool is a plugin, so new ones slot in as another rung.
See How escalation works and the full list of integrations.
Known walls
It's an alpha, and some sites still win:
Need the paid tools: in a free-only spot check, Etsy, Home Depot, Yelp, Crunchbase and G2 blocked every free tool.
Beat everything so far: Shopee, Temu and Idealista.
Social sites without a login: LinkedIn, X, YouTube, Threads, Bluesky and Reddit read fine. Instagram, TikTok, Facebook and Pinterest show only the public shell; the posts need a login.
Logged-in pages (your feeds, your orders) need a profile.
A slow tail: most reads take a few seconds, but one in ten climbs several tools and takes 25 s or more.
Found a site it can't read? Report it; every report becomes a test case.
Develop
python3 -m venv .venv
.venv/bin/pip install -e '.[test,mcp]'
.venv/bin/frankensurf install
PYTHONPATH=.:src .venv/bin/pytest -qThe product design is in SPEC.rst and contributor rules in AGENTS.md. New tools are plugins,
never branches in Core: see Writing a plugin and the
example in examples/frankensurf-plugin-example. The website and docs live in site/.
Licence
Apache-2.0. See LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Web search and page reading for AI agents, including JSON APIs, RSS feeds and YouTube.
Read any web page as clean Markdown for AI agents: fetch, search, metadata, links. SSRF-safe.
Web scraping for agents. Point it at a URL and it returns the page as clean markdown, JavaScript-rendered pages included. Point it at a site and it maps the URLs or crawls the section you need in the background, a few pages at a time so results fit in the conversation. Search the web and read full pages, extract fields with a JSON schema you define (validated, never invented), read a store's catalogue or a blog's posts from the platform's own feed, and check whether a page has changed. Failed requests cost nothing. The free plan includes 1,500 credits a month.
Read a URL as clean markdown, screenshot a website, url to PDF. Web access for agents, no signup.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceSearch the web using DuckDuckGo and fetch/convert web content using Jina Reader. Privacy-focused search with no API key required.216 PyPI10MIT
- AlicenseNot gradedqualityDmaintenanceWeb search, clean page reading & one-call research dossiers for AI agents. No API key — your agent does the synthesis.58 npmMIT
- AlicenseNot gradedqualityCmaintenanceProvides a free, no-paid-API web search gateway for AI agents using DuckDuckGo and Bing HTML scrapers, with tools for search, URL fetching, and text extraction.MIT
- FlicenseAqualityCmaintenanceEnables keyless web search across multiple engines with fallback and relevance ranking, plus anonymous HTTP(S) page fetching, all without API keys or vendor dependencies.21-