# Synoppy > The web data layer for AI agents. One API to read, crawl, extract, and > understand the entire web — clean, LLM-ready data without running your own > scraping infrastructure. ## Products - Read (live): any URL → clean markdown, HTML, or plain text with metadata - Crawl (live): whole-site crawling, one clean page per URL - Map (live): URL discovery without reading every page (sitemap.xml or same-origin links) - Extract (live): AI-structured JSON in the shape you describe - Classify (live): industry + NAICS / SIC codes (taxonomy-validated), or your own labels - Enrich (live): brand data — logos, colors, fonts, socials, description, address - Images (live): every image on a page with alt text - Screenshot (live): capture any URL as a PNG - JS rendering (live): render SPA / client-side pages with render:true or render:"auto" - Act (coming soon): goal-driven browser agents — navigate, fill forms, authenticate ## API Base URL: https://synoppy.com Auth: header `Authorization: Bearer YOUR_API_KEY` — create a key at https://synoppy.com/dashboard All endpoints are POST with a JSON body and return JSON. Every successful response includes `creditsUsed` and `creditsRemaining` (billing is metered per request). ### Endpoints (all live) - POST /api/scrape — Read a URL. Body: { url, formats?: ["markdown"|"html"|"text"], onlyMainContent?: bool, render?: bool|"auto", waitMs?: number, timeoutMs?: number }. Returns: markdown?/html?/text?, metadata{title,description,language,siteName,author,ogImage,sourceUrl,statusCode,wordCount,fetchedAt,rendered,bytesIn}, latencyMs. - POST /api/crawl — Crawl a site (requires key). Body: { url, limit?: 1-25 (default 10) }. Returns: domain, discovered, count, pages[{url,title,markdown,words}]. - POST /api/map — Discover URLs. Body: { url }. Returns: domain, urls[], count, source: "sitemap"|"links". Also accepts GET ?url=. - POST /api/extract — AI-structured JSON (requires key). Body: { url, prompt?: string }. Returns: url, model: "synoppy-extract-1", data, usage{inputTokens,outputTokens}. - POST /api/classify — Industry/NAICS/SIC or custom labels (requires key). Body: { url, labels?: string[] }. Returns: data{industry,naics_code,sic_code,categories,confidence} OR (with labels) {label,confidence,reasoning}. - POST /api/brand — Enrich a brand. Body: { url } | { domain } | { email }. Returns: domain, name, description, logo, colors[], fonts[], address, socials[{label,url}]. Also accepts GET ?domain=|?url=|?email=. - POST /api/images — Images on a page. Body: { url }. Returns: url, count, images[{src,alt,width,height}]. - POST /api/screenshot — PNG capture. Body: { url, fullPage?: bool, waitMs?: number, timeoutMs?: number }. Returns: screenshot (base64 PNG data URL), sourceUrl, statusCode, fullPage. - POST /api/act — Coming soon (not live yet). ### Errors Consistent shape: { "success": false, "error": "human message", "code": "MACHINE_CODE" }. Codes: BAD_REQUEST (400), INVALID_KEY (401), AUTH_REQUIRED (401, AI/crawl endpoints need a key), NO_CREDITS (402), BLOCKED_HOST (400), UNSUPPORTED_FORMAT (415, e.g. PDFs on Read), RATE_LIMITED (429), RENDER_UNAVAILABLE (503, Screenshot/JS-render backend off), UPSTREAM_ERROR (502). ### SDKs & MCP - TypeScript/JavaScript: npm i @synoppy/sdk → new Synoppy({ apiKey }).read(url) - Python: pip install synoppy → Synoppy(api_key=...).read(url) - Ruby: gem install synoppy → Synoppy::Client.new(api_key:).read(url) - Go: go get github.com/Synoppy/synoppy-go → synoppy.New(key).Read(ctx, url, nil) - MCP server: npx -y @synoppy/mcp (exposes every endpoint as a tool for Claude, Cursor, etc.) - Full docs: https://synoppy.com/docs ## Pricing - Credit-based, pooled across products. Free tier includes 1,000 credits/mo. - Costs scale with the work done (a JS-rendered or AI-extracted page costs more than a simple static read). See https://synoppy.com/pricing. ## Contact - https://synoppy.com