Sniff out any page.
Get clean data back.
SnoopScan is a web scraping API for AI agents. One call turns any public page into markdown, links or JSON in your own schema — including the pages that block everything else.
Paste the setup prompt into your AI chat and your agent does the rest. 1,500 credits a month free, no card. Or try it right here:
Try it on a competitor pricing page, a product listing, a docs page for your RAG index or a company about page — or one of these:
Every tool. One key.
One key, plain REST and JSON. Pick a tool and the call appears beside it, ready to paste.
import requestsr = requests.post( 'https://api.snoopscan.com/v1/scrape', headers={'Authorization': 'Bearer sk_YOUR_KEY'}, json={ 'url': 'https://example.com/pricing', 'formats': [ 'markdown', 'links' ], 'onlyMainContent': True },)print(r.json())
const r = await fetch('https://api.snoopscan.com/v1/scrape', { method: 'POST', headers: { Authorization: 'Bearer sk_YOUR_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ "url": "https://example.com/pricing", "formats": [ "markdown", "links" ], "onlyMainContent": true }),});console.log(await r.json());
curl -X POST https://api.snoopscan.com/v1/scrape \ -H 'Authorization: Bearer sk_YOUR_KEY' \ -H 'Content-Type: application/json' \ -d '{ "url": "https://example.com/pricing", "formats": [ "markdown", "links" ], "onlyMainContent": true}'
import requestsr = requests.post( 'https://api.snoopscan.com/v1/crawl', headers={'Authorization': 'Bearer sk_YOUR_KEY'}, json={ 'url': 'https://example.com', 'limit': 100, 'maxDepth': 3, 'includePaths': [ '/blog/*' ] },)print(r.json())
const r = await fetch('https://api.snoopscan.com/v1/crawl', { method: 'POST', headers: { Authorization: 'Bearer sk_YOUR_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ "url": "https://example.com", "limit": 100, "maxDepth": 3, "includePaths": [ "/blog/*" ] }),});console.log(await r.json());
curl -X POST https://api.snoopscan.com/v1/crawl \ -H 'Authorization: Bearer sk_YOUR_KEY' \ -H 'Content-Type: application/json' \ -d '{ "url": "https://example.com", "limit": 100, "maxDepth": 3, "includePaths": [ "/blog/*" ]}'
import requestsr = requests.post( 'https://api.snoopscan.com/v1/map', headers={'Authorization': 'Bearer sk_YOUR_KEY'}, json={ 'url': 'https://example.com', 'search': 'pricing' },)print(r.json())
const r = await fetch('https://api.snoopscan.com/v1/map', { method: 'POST', headers: { Authorization: 'Bearer sk_YOUR_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ "url": "https://example.com", "search": "pricing" }),});console.log(await r.json());
curl -X POST https://api.snoopscan.com/v1/map \ -H 'Authorization: Bearer sk_YOUR_KEY' \ -H 'Content-Type: application/json' \ -d '{ "url": "https://example.com", "search": "pricing"}'
import requestsr = requests.post( 'https://api.snoopscan.com/v1/search', headers={'Authorization': 'Bearer sk_YOUR_KEY'}, json={ 'query': 'best headless browsers', 'limit': 5, 'scrapeOptions': { 'formats': [ 'markdown' ] } },)print(r.json())
const r = await fetch('https://api.snoopscan.com/v1/search', { method: 'POST', headers: { Authorization: 'Bearer sk_YOUR_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ "query": "best headless browsers", "limit": 5, "scrapeOptions": { "formats": [ "markdown" ] } }),});console.log(await r.json());
curl -X POST https://api.snoopscan.com/v1/search \ -H 'Authorization: Bearer sk_YOUR_KEY' \ -H 'Content-Type: application/json' \ -d '{ "query": "best headless browsers", "limit": 5, "scrapeOptions": { "formats": [ "markdown" ] }}'
import requestsr = requests.post( 'https://api.snoopscan.com/v1/extract', headers={'Authorization': 'Bearer sk_YOUR_KEY'}, json={ 'urls': [ 'https://example.com/pricing' ], 'schema': { 'type': 'object', 'properties': { 'plan': { 'type': 'string' }, 'price': { 'type': 'number' } } }, 'prompt': 'The cheapest paid plan' },)print(r.json())
const r = await fetch('https://api.snoopscan.com/v1/extract', { method: 'POST', headers: { Authorization: 'Bearer sk_YOUR_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ "urls": [ "https://example.com/pricing" ], "schema": { "type": "object", "properties": { "plan": { "type": "string" }, "price": { "type": "number" } } }, "prompt": "The cheapest paid plan" }),});console.log(await r.json());
curl -X POST https://api.snoopscan.com/v1/extract \ -H 'Authorization: Bearer sk_YOUR_KEY' \ -H 'Content-Type: application/json' \ -d '{ "urls": [ "https://example.com/pricing" ], "schema": { "type": "object", "properties": { "plan": { "type": "string" }, "price": { "type": "number" } } }, "prompt": "The cheapest paid plan"}'
import requestsr = requests.post( 'https://api.snoopscan.com/v1/batch/scrape', headers={'Authorization': 'Bearer sk_YOUR_KEY'}, json={ 'urls': [ 'https://example.com/a', 'https://example.com/b' ], 'maxConcurrency': 10, 'scrapeOptions': { 'formats': [ 'markdown' ] } },)print(r.json())
const r = await fetch('https://api.snoopscan.com/v1/batch/scrape', { method: 'POST', headers: { Authorization: 'Bearer sk_YOUR_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ "urls": [ "https://example.com/a", "https://example.com/b" ], "maxConcurrency": 10, "scrapeOptions": { "formats": [ "markdown" ] } }),});console.log(await r.json());
curl -X POST https://api.snoopscan.com/v1/batch/scrape \ -H 'Authorization: Bearer sk_YOUR_KEY' \ -H 'Content-Type: application/json' \ -d '{ "urls": [ "https://example.com/a", "https://example.com/b" ], "maxConcurrency": 10, "scrapeOptions": { "formats": [ "markdown" ] }}'
import requestsr = requests.post( 'https://api.snoopscan.com/v1/products', headers={'Authorization': 'Bearer sk_YOUR_KEY'}, json={ 'url': 'https://store.example.com', 'limit': 500 },)print(r.json())
const r = await fetch('https://api.snoopscan.com/v1/products', { method: 'POST', headers: { Authorization: 'Bearer sk_YOUR_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ "url": "https://store.example.com", "limit": 500 }),});console.log(await r.json());
curl -X POST https://api.snoopscan.com/v1/products \ -H 'Authorization: Bearer sk_YOUR_KEY' \ -H 'Content-Type: application/json' \ -d '{ "url": "https://store.example.com", "limit": 500}'
import requestsr = requests.post( 'https://api.snoopscan.com/v1/posts', headers={'Authorization': 'Bearer sk_YOUR_KEY'}, json={ 'url': 'https://blog.example.com', 'limit': 200 },)print(r.json())
const r = await fetch('https://api.snoopscan.com/v1/posts', { method: 'POST', headers: { Authorization: 'Bearer sk_YOUR_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ "url": "https://blog.example.com", "limit": 200 }),});console.log(await r.json());
curl -X POST https://api.snoopscan.com/v1/posts \ -H 'Authorization: Bearer sk_YOUR_KEY' \ -H 'Content-Type: application/json' \ -d '{ "url": "https://blog.example.com", "limit": 200}'
import requestsr = requests.post( 'https://api.snoopscan.com/v1/monitor', headers={'Authorization': 'Bearer sk_YOUR_KEY'}, json={ 'name': 'Pricing', 'urls': [ 'https://example.com/pricing' ], 'intervalMinutes': 60, 'webhook': 'https://hooks.example.com/snoop' },)print(r.json())
const r = await fetch('https://api.snoopscan.com/v1/monitor', { method: 'POST', headers: { Authorization: 'Bearer sk_YOUR_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ "name": "Pricing", "urls": [ "https://example.com/pricing" ], "intervalMinutes": 60, "webhook": "https://hooks.example.com/snoop" }),});console.log(await r.json());
curl -X POST https://api.snoopscan.com/v1/monitor \ -H 'Authorization: Bearer sk_YOUR_KEY' \ -H 'Content-Type: application/json' \ -d '{ "name": "Pricing", "urls": [ "https://example.com/pricing" ], "intervalMinutes": 60, "webhook": "https://hooks.example.com/snoop"}'
import requestsr = requests.post( 'https://api.snoopscan.com/v1/places/search', headers={'Authorization': 'Bearer sk_YOUR_KEY'}, json={ 'query': 'coffee shops', 'location': 'Austin, TX', 'limit': 20, 'enrich': True },)print(r.json())
const r = await fetch('https://api.snoopscan.com/v1/places/search', { method: 'POST', headers: { Authorization: 'Bearer sk_YOUR_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ "query": "coffee shops", "location": "Austin, TX", "limit": 20, "enrich": true }),});console.log(await r.json());
curl -X POST https://api.snoopscan.com/v1/places/search \ -H 'Authorization: Bearer sk_YOUR_KEY' \ -H 'Content-Type: application/json' \ -d '{ "query": "coffee shops", "location": "Austin, TX", "limit": 20, "enrich": true}'
import requestsr = requests.post( 'https://api.snoopscan.com/v1/domain', headers={'Authorization': 'Bearer sk_YOUR_KEY'}, json={ 'domain': 'https://example.com', 'backlinkLimit': 100 },)print(r.json())
const r = await fetch('https://api.snoopscan.com/v1/domain', { method: 'POST', headers: { Authorization: 'Bearer sk_YOUR_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ "domain": "https://example.com", "backlinkLimit": 100 }),});console.log(await r.json());
curl -X POST https://api.snoopscan.com/v1/domain \ -H 'Authorization: Bearer sk_YOUR_KEY' \ -H 'Content-Type: application/json' \ -d '{ "domain": "https://example.com", "backlinkLimit": 100}'
import requestsr = requests.post( 'https://api.snoopscan.com/v1/domain/report', headers={'Authorization': 'Bearer sk_YOUR_KEY'}, json={ 'domain': 'example.com', 'depth': 'buyer' },)print(r.json())
const r = await fetch('https://api.snoopscan.com/v1/domain/report', { method: 'POST', headers: { Authorization: 'Bearer sk_YOUR_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ "domain": "example.com", "depth": "buyer" }),});console.log(await r.json());
curl -X POST https://api.snoopscan.com/v1/domain/report \ -H 'Authorization: Bearer sk_YOUR_KEY' \ -H 'Content-Type: application/json' \ -d '{ "domain": "example.com", "depth": "buyer"}'
import requestsr = requests.post( 'https://api.snoopscan.com/v1/domain/screen', headers={'Authorization': 'Bearer sk_YOUR_KEY'}, json={ 'domains': [ 'example.com', 'example.io', 'example.net' ], 'dns': True },)print(r.json())
const r = await fetch('https://api.snoopscan.com/v1/domain/screen', { method: 'POST', headers: { Authorization: 'Bearer sk_YOUR_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ "domains": [ "example.com", "example.io", "example.net" ], "dns": true }),});console.log(await r.json());
curl -X POST https://api.snoopscan.com/v1/domain/screen \ -H 'Authorization: Bearer sk_YOUR_KEY' \ -H 'Content-Type: application/json' \ -d '{ "domains": [ "example.com", "example.io", "example.net" ], "dns": true}'
import requestsr = requests.post( 'https://api.snoopscan.com/v1/leads', headers={'Authorization': 'Bearer sk_YOUR_KEY'}, json={ 'who': 'roofing contractors', 'where': 'Houston, TX', 'limit': 50 },)print(r.json())
const r = await fetch('https://api.snoopscan.com/v1/leads', { method: 'POST', headers: { Authorization: 'Bearer sk_YOUR_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ "who": "roofing contractors", "where": "Houston, TX", "limit": 50 }),});console.log(await r.json());
curl -X POST https://api.snoopscan.com/v1/leads \ -H 'Authorization: Bearer sk_YOUR_KEY' \ -H 'Content-Type: application/json' \ -d '{ "who": "roofing contractors", "where": "Houston, TX", "limit": 50}'
import requestsr = requests.post( 'https://api.snoopscan.com/v1/company', headers={'Authorization': 'Bearer sk_YOUR_KEY'}, json={ 'url': 'https://example.com', 'contacts': True },)print(r.json())
const r = await fetch('https://api.snoopscan.com/v1/company', { method: 'POST', headers: { Authorization: 'Bearer sk_YOUR_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ "url": "https://example.com", "contacts": true }),});console.log(await r.json());
curl -X POST https://api.snoopscan.com/v1/company \ -H 'Authorization: Bearer sk_YOUR_KEY' \ -H 'Content-Type: application/json' \ -d '{ "url": "https://example.com", "contacts": true}'
Same shape for every tool. A URL or a list, a few options, and back comes data plus what it cost.
One URL in. Structured data out.
Send a URL and get back markdown, links or JSON in the shape you asked for. Pages that block bots or need JavaScript come back the same way, with nothing to configure.
POST /v1/scrape
{ "url": "https://example.com/pricing", "formats": ["markdown", "links"]}
200 · 1 credit
{ "success": true, "data": { "markdown": "# Pricing\n\nStarter — $12 a month…", "links": ["/signup", "/docs", "/enterprise"], "metadata": { "title": "Pricing", "statusCode": 200 }, "cost": { "credits": 1, "cached": false } }}
Most pages cost one credit. You pay for what worked.
An ordinary page costs 1 credit. Pages that need a premium proxy or a browser cost more, and the pricing page lists every rate. Failed requests are never charged.
Blocked pages come back. Nothing to configure.
Bot walls, pages that only exist once JavaScript has run, sites that want a particular country: one call, the same shape every time. What each kind of page costs is on the pricing page, and in your activity log after every call.
Most of the web. Fast, and 1 credit.
Sites that block bots still come back. Pick the country the request should come from; 12 to choose from.
Pages that render in the browser come back fully loaded. Interact can click, type and scroll first.
Ask again for a page you already fetched and it comes back free. You set how fresh it needs to be.
Open the page in the free web unblocker: read it as markdown or browse it in a frame, from the country you pick. No account, no scripts, no cookies.
The rest of the job, already done.
PDFs and documents come back as text and tables, priced by the page.
A JSON schema and up to 100 URLs in, rows out.
Click, type, scroll and wait in a real browser before the page is read.
Watch a page on a schedule and see what changed, run by run.
Thousands of URLs as one job, with a webhook when it finishes.
Ask again for a page you already fetched and it costs nothing. You set the window per request.
The work people buy this for.
Common jobs, and the endpoints that do them.
Crawl a whole site into markdown that chunks cleanly, and keep the index fresh as the source moves.
Read a product page for price, stock and variants, on one store or ten thousand, and know the hour a figure moves.
Search the web and read every result in full instead of a snippet, then map a competitor site end to end.
Map a company site, keep the pages that matter, and pull people, roles and contact details into your columns.
Track what a rival publishes, prices and promises, and get told the moment any of it changes.
Property, flights, fares and stock: pages built by JavaScript, read the same way as any other.
Plug it into the tools you already use.
Every tool is also an MCP server. Paste one line into Claude Code, Codex, Cursor, the Claude app or ChatGPT, and your agent connects it for you. Anything that speaks plain HTTP gets the same API.
Read and follow https://snoopscan.com/agent-onboarding/SKILL.md
And any other MCP client: a URL and a header is all it takes.
Python, Node, cURL, or anything that can make an HTTP request. Nothing to install.
Crawls and batches call you back when they finish, so nothing polls.
Invite people from Team. Everyone shares the credits, and every request shows who made it.
Every call you made, what came back and what it cost.
Priced by the page. From $0.45 a thousand.
One allowance across every tool. A failed request is never billed, and re-reading your own cached page costs nothing.
The questions people ask first.
What is SnoopScan?+
A web scraping API for AI agents. Give it a URL and it hands back the page as clean markdown, HTML, links or JSON in your own schema. It handles the fetching, the proxies, the browser and the parsing, so you never build or babysit scraping infrastructure.
Who is it for?+
Developers and teams whose agents, research pipelines or products need pages from the web: agent builders, deep research, lead enrichment, price and stock monitoring, RAG and search indexes.
Which sites can it reach?+
Most public pages, including pages that need JavaScript and pages that block bots. Pages behind a login are not supported.
Is web scraping legal?+
Scraping public pages is lawful in most places; what you do with the data is governed by the site's terms and by privacy law where you are. You are responsible for how you use what you collect.
Does it work in Claude Code, Codex, Cursor or ChatGPT?+
Yes. SnoopScan is an MCP server, so any AI app or agent that supports MCP can use it: Claude Code, Codex, Cursor, VS Code, Windsurf, the Claude app, ChatGPT and more. Paste "Read and follow https://snoopscan.com/agent-onboarding/SKILL.md" into the chat and the agent sets it up. You sign in and press Approve.
Is there an MCP server?+
Yes, at https://api.snoopscan.com/mcp. Its tools scrape, crawl, map, search and extract, list a store's products or a blog's posts, check pages for changes, and look up domains and companies. The Claude app and ChatGPT connect at https://api.snoopscan.com/mcp-oauth by signing in, with no key to copy.
Do I need to install anything?+
No. The MCP server and the API are hosted. When an agent sets SnoopScan up, it runs any command itself; you only sign in and press Approve in your browser.
What does a credit buy?+
One page. Most pages cost 1 credit. Pages that need a premium proxy or a browser cost more, and re-reading a page you already fetched is free. The rate card on the pricing page lists every unit, and your activity log shows what each call cost.
Am I charged for failed requests?+
No. A request that fails carries no cost and never counts against your balance. You only pay for pages that come back.
What is the difference between scrape and crawl?+
Scrape reads the pages you name. Crawl discovers pages by following links from a start URL, with depth and path filters, and reads each one. Map lists a site's URLs without reading them, which is the cheap way to decide what to crawl.
What formats come back?+
Markdown, HTML, raw HTML, links, a summary, a screenshot, or JSON shaped to a schema you give it. Ask for several in one call. PDFs and Word documents come back as text through Parse.
Does it work with my stack?+
It is plain REST and JSON. Python, Node, cURL, or anything that can make an HTTP request. Nothing to install.
Can I extract data with a prompt?+
Yes. Extract takes a JSON schema and, optionally, a prompt, and answers per page with a confidence score. For fixed shapes at volume, a schema alone is more consistent than a prompt.
Do I need an AI key to use Extract?+
No. Extract reads a page's own structured markup and fills your schema from that. For fields the markup cannot answer you can add your own Anthropic or OpenAI key in your account; it runs on your key and costs no credits.
How do long jobs report back?+
Crawls and batches return a job id. Poll it, or give a webhook URL and the job calls you when it finishes.
Can my team share an account?+
Yes. Invite people from Team. Everyone shares the credits and keys, and every request shows who made it.
Is there a free plan?+
Yes. 1,500 credits a month, refreshed on the day you signed up, no card needed. It is a real plan, not a trial that expires.
Do unused credits roll over?+
No. Your free credits refresh monthly on the day you signed up, and your dashboard shows the date. Paid plans refresh on their billing date.
What happens when I run out?+
Requests return a clear 402 with the reason, and nothing is charged. Move up a plan from Billing and the credits land the same day.
Can I switch plans later?+
Yes, from Billing, up or down. A move up applies straight away; a move down applies when the period you paid for ends. Billing says which before you confirm.
Can I try it without signing up?+
Yes. An AI agent can call scrape, search and parse with no key at all, over the MCP server or the API: 20 free successful calls a day, on plain pages. Every answer says how many are left, and a blocked page does not use one up. Pages that need a browser, and anything past 20 a day, need the free account.
Where does my data go?+
Fetched pages are cached briefly, then dropped. Re-reading your own cached page is free. Nothing you scrape is used for anything else.
Try it on a page you actually need.
Paste the setup prompt into your AI chat, or try a URL in the Playground and copy the code it gives you. The first 1,500 credits are on us.
Start for free