AnakinScraper OSS
The open-source web scraping API for AI. Turn any website into LLM-ready markdown or structured data.
Self-host with a single command. No cloud dependencies. Powers RAG pipelines, AI agents, and data extraction at scale.
git clone https://github.com/Anakin-Inc/anakinscraper-oss.git && cd anakinscraper-oss && make up
# Scrape any website — one curl, full result:
curl -s -X POST http://localhost:8080/v1/scrape \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}' | jq .markdown
Why AnakinScraper?
| AnakinScraper | Firecrawl | Crawlee | Scrapy | |
|---|---|---|---|---|
| Anti-detect browser | Camoufox (Firefox) | Headless Chrome | Playwright | No |
| Smart proxy selection | Thompson Sampling (ML) | Round-robin | Manual | Manual |
| Zero-config start | go run — no DB needed |
Docker required | npm install | pip install |
| Single binary | Go — one 30MB binary | Node.js | Node.js | Python |
| Handler chain fallback | HTTP → Browser → API | Single mode | Single mode | Single mode |
| Structured JSON (AI) | Gemini extraction | LLM extraction | No | No |
Features
- Handler chain with fallback — HTTP fetch → anti-detect browser → external API. Each handler tries in order; if one fails, the next picks up automatically. Most pages resolve on the free local HTTP handler — paid APIs are only called for the ~5% that actually need them. Docs →
- Custom API handlers — plug in any third-party scraping service as a chain fallback. Only invoked when local handlers fail — saves 90%+ on API costs vs routing everything through a paid service. Built-in anakin.io handler included. How to add your own →
- Domain configs — per-domain scraping strategies: choose which handlers to use, set timeouts, retries, custom headers, block domains, and validate content with pattern matching. Docs →
- Failure detection — define failure patterns and required patterns per domain. If the scraped content matches a failure pattern (e.g. CAPTCHA page) or misses a required pattern, the job auto-retries with the next handler. Docs →
- Anti-detect browser — Camoufox (anti-detect Firefox) with realistic fingerprints, not headless Chrome. Docs →
- Proxy auto-select — Thompson Sampling picks the best proxy per domain, learning from success/failure in real time. Docs →
- Structured JSON extraction — use Gemini AI to extract structured data from any page (bring your own API key)
- Sync + async + batch API —
POST /v1/scrapefor instant results,/v1/url-scraperfor async with polling, batch up to 10 URLs - LLM-ready markdown — automatic boilerplate removal, clean content extraction. Feed directly into RAG pipelines, Claude, GPT, or any LLM without preprocessing
- Web dashboard — built-in React UI for scraping, job tracking, domain config management, and proxy monitoring
- Zero-config mode — run with just Go, no database needed. Or use Docker for the full stack
- Self-contained — no Redis, no AWS, no message queues. Single Go binary. Optional PostgreSQL for persistence
Quick Start (no Docker, no database)
Just Go 1.25+. Two commands:
cd server && go run cmd/server/main.go
# In another terminal:
curl -s -X POST http://localhost:8080/v1/scrape \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}' | jq .markdown
Jobs are stored in memory (lost on restart). For persistence, set DATABASE_URL. For JavaScript-heavy sites, add the browser service via Docker.
Self-Host (Docker — full stack)
Prerequisites
- Docker and Docker Compose
Start
git clone https://github.com/Anakin-Inc/anakinscraper-oss.git
cd anakinscraper-oss
make up
That's it. Three containers start:
| Service | Port | Description |
|---|---|---|
| Server | 8080 | REST API + worker pool |
| Browser Service | 9222 | Camoufox anti-detect browser (WebSocket) |
| PostgreSQL | 5432 | Job storage |
Web Dashboard
A built-in web UI is included for visual scraping, job tracking, and configuration:
cd webapp && npm install && npm run dev
Open http://localhost:3000 — the dashboard proxies API calls to the server on port 8080.
Pages: Dashboard (health + quick scrape) | Scrape (sync/async/batch with live results) | Jobs (tracked history with status filters) | Domain Configs (CRUD with handler chain management) | Proxy Scores (Thompson Sampling performance)
Scrape a URL
Synchronous (recommended for getting started):
curl -s -X POST http://localhost:8080/v1/scrape \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}' | jq .
One request, full result back. No polling. Timeout: 30 seconds by default (configurable via the timeout request field, max 120 seconds).
Asynchronous (for long-running scrapes):
# Submit
curl -s -X POST http://localhost:8080/v1/url-scraper \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}'
# Poll for result
curl -s http://localhost:8080/v1/url-scraper/JOB_UUID | jq .
With AI-powered JSON extraction (requires GEMINI_API_KEY):
curl -s -X POST http://localhost:8080/v1/scrape \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "generateJson": true}' | jq .generatedJson
No API keys required for the scraper itself. Just JSON in, results out.
Architecture
┌─────────────────┐
│ Your App │
│ (cURL / CLI) │
└────────┬────────┘
│ HTTP
▼
┌─────────────────┐ ┌──────────┐
│ Server │────────▶│ Gemini │
│ (Go/Fiber) │ optional│ (JSON) │
│ Port 8080 │ └──────────┘
└──┬──────┬───┬──┘
│ │ │
┌──────────┘ │ └────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────────┐ ┌──────────────┐
│ Storage │ │ Browser │ │ API Handler │
│ Postgres │ │ Service │ │ (anakin.io │
│ or memory│ │ (Camoufox) │ │ or custom) │
│(optional)│ │ (optional) │ │ (optional) │
└──────────┘ └──────────────┘ └──────────────┘
The server is a single Go binary that runs with zero dependencies. Optionally add PostgreSQL for persistence, the browser service for JavaScript-heavy sites, and API handlers for hard-to-scrape sites. Workers execute the handler chain (HTTP → browser → API fallback), convert HTML to markdown, and optionally extract structured JSON via Gemini.
API Reference
See docs/API.md for the complete API reference. Quick overview:
| Method | Endpoint | Description |
|---|---|---|
POST |
/v1/scrape |
Sync — scrape a URL and get the result back directly (default 30s timeout, configurable via timeout field, max 120s) |
POST |
/v1/url-scraper |
Async — submit a scrape job, returns job ID |
GET |
/v1/url-scraper/:id |
Poll for async job result |
POST |
/v1/url-scraper/batch |
Batch scrape up to 10 URLs |
GET |
/v1/url-scraper/batch/:id |
Poll for batch result |
POST |
/v1/domain-configs |
Create a per-domain scraping config |
GET |
/v1/domain-configs |
List all domain configs |
GET |
/v1/proxy/scores |
View proxy Thompson Sampling scores |
GET |
/v1/telemetry/status |
View telemetry state and next payload (details) |
GET |
/health |
Health check |
Request Fields
| Field | Type | Default | Description |
|---|---|---|---|
url |
string | required | URL to scrape |
useBrowser |
bool | false |
Skip HTTP handler, go stra |