Skip to main content
Glama

πŸ•·οΈ LookaCrawler

Free, open-source, token-efficient local alternative to Firecrawl with native Model Context Protocol (MCP) Server for LLMs.

License: MIT Bun TypeScript MCP Ready GitHub Stars Local-First


πŸ“Œ Why LookaCrawler?

Web crawling for Large Language Models (LLMs) is broken by default: modern web pages contain massive HTML bloat (scripts, tracking pixels, nested divs, navigation headers, stylesheets), costing thousands of wasted tokens per page.

LookaCrawler is an open-source, token-optimized local crawler that cuts a median 90% of tokens on real pages (21–98% across 8 sites, see benchmark-live.ts), extracts clean Markdown, renders JavaScript-heavy pages with a real browser, and exposes a native Model Context Protocol (MCP) Server ready for Claude Desktop, Cursor, and Antigravity.


Related MCP server: TheCrawler

πŸ₯Š Comparison: LookaCrawler vs Alternatives

Feature

πŸ•·οΈ LookaCrawler

πŸ”₯ Firecrawl (Cloud)

⚑ Jina Reader

Pricing / Cost

$0.00 (100% Free Open Source)

$16 to $99+/month

Rate-limited API

Token Reduction

Median 90% fewer tokens (real pages) + Footnotes

Standard Markdown

Basic Markdown

Autonomous Crawling

Native map & crawl (BFS + URL patterns)

Cloud Crawler

Single-page only

Pre-Crawl Actions

Native Playwright (click, scroll, fill)

Paid Addon

None

Link Formatting

Inline, References Footnotes, Strip

Inline only

Inline only

Data Privacy

Local-first (Zero Telemetry)

Cloud Provider

Cloud API

MCP Integration

Native Tools + Resources + Prompts

Community Wrapper

None

JS Rendering

Real Chrome (Playwright)

Cloud Proxies

Basic Headers

Local SQLite Cache

Built-in (24h TTL cache)

Redis / Paid Addon

None

JS SPA Support

Playwright + Chrome Pool

Cloud Headless

Headless


πŸš€ Key Features

  • Token Economy First: Automatically prunes scripts, styles, inline SVGs, tracking tags, navigations, footers, redundant forms, and boilerplate containers with high link density (>80%).

  • Advanced Link & Image Formatting:

    • link_format: Choose between inline (standard markdown), references (footnote citations [1], saving ~25% tokens on repetitive URLs), or strip (pure text).

    • image_mode: Choose between ignore (zero tokens), alt_only (preserves semantic context without URL bloat), or markdown (full ![alt](url)).

  • Autonomous Mapping & Recursive Crawling:

    • map_website: Inspects /robots.txt, sitemaps, and root anchors to discover all pages in a domain.

    • crawl_website: Breadth-first autonomous crawling with max depth, max pages, URL pattern filters (substring, * wildcard), and real-time token accounting.

  • Pre-Crawl Browser Actions: Automate clicks, scrolls, typing, and waits in Playwright before extracting content (dismiss cookie banners, scroll for infinite loading, expand accordions).

  • Dual Hybrid Crawling Engine:

    • fast: Ultra-fast native HTTP GET with backoff. Escalates to deep when a page needs JavaScript to render.

    • deep: Headless Playwright engine launching real Google Chrome for pages that need JavaScript. Challenge pages (CAPTCHA, bot checks) are detected and reported instead of retried.

  • Native MCP Ecosystem:

    • Tools: extract_web_content, crawl_website, map_website, batch_extract_web_content, extract_structured_data, extract_contacts, search_places, discover_local_leads, deep_enrich_lead, lint_anti_slop, lookup_social_profile, search_social_intent, audit_company_website, analyze_competitors, generate_growth_plan, gtm_pipeline_run.

    • Resources: Live telemetry at crawler://metrics and cache analytics at crawler://cache/stats.

    • Prompts: Pre-engineered templates crawl-and-summarize and compare-pages.

  • Entity Extraction: contacts pulls emails, phone numbers, WhatsApp links and social profiles; places returns structured Google Maps business records with formula-injection-safe CSV output.

  • B2B Lead Discovery: maps (Google Maps engine) plus enrich, which crawls a company's own site for verified emails, socials and decision makers.

  • GTM Toolkit (no paid APIs): audit (SEO + conversion checklist), intel (audit + Maps competitor review + deterministic growth plan), gtm (Maps discovery, enrichment, outreach draft written to JSONL/CSV; never sends anything), antislop (AI-slop copy linter), intent (pt-BR/EN buying-intent scorer), social-lookup and intent-search (public profile meta tags, Reddit .json), daemon (Maps scraper web-mode service).

  • Local SQLite Caching: Stores extracted Markdown in crawler_cache.sqlite to eliminate duplicate network calls.

  • Structured JSON & Metadata Extraction: Extracts Open Graph tags (og:title, og:description), publication dates, canonical URLs, and custom CSS selectors.


πŸ”Œ 1-Click MCP Setup (Claude Desktop & Cursor)

Add LookaCrawler to your claude_desktop_config.json or Cursor MCP settings:

{
  "mcpServers": {
    "lookacrawler": {
      "command": "bun",
      "args": ["run", "/absolute/path/to/lookacrawler/index.ts"]
    }
  }
}

Now you can prompt Claude or Cursor:

"Crawl https://example.com/docs and extract the API documentation using LookaCrawler."


πŸ“¦ Quick Start & CLI Usage

1. Installation

Requires Bun 1.1+ (high-performance runtime with native SQLite):

# Clone the repository
git clone https://github.com/lucasmartins-ai/lookacrawler.git
cd lookacrawler

# Install dependencies
bun install

2. CLI Commands

# Single URL fast Markdown extraction
bun run cli.ts extract https://news.ycombinator.com --mode fast

# Single URL fast Markdown extraction with reference footnotes
bun run cli.ts extract https://example.com --link-format references --output page.md

# Headless Playwright deep extraction with CSS selector target
bun run cli.ts extract https://example.com --mode deep --selector "main" --json

# Discover all website URLs and sitemaps
bun run cli.ts map https://example.com --max-urls 500

# Recursively crawl documentation with URL pattern filtering and token accounting
bun run cli.ts crawl https://example.com/docs --max-depth 2 --max-pages 15 --include /docs/ --link-format references

# Batch concurrent multi-URL crawling
bun run cli.ts batch https://site1.com https://site2.com --concurrency 4

# Structured JSON schema extraction
bun run cli.ts structured https://example.com --schema '{"title":"h1","links":"a"}'

# Extract emails, phones, WhatsApp links and social profiles from a site
bun run cli.ts contacts https://example.com

# Search local businesses on Google Maps (browser-driven)
bun run cli.ts places "dentists in Bristol" --limit 5 --csv -o places.csv

# B2B lead discovery via the bundled google-maps-scraper engine
# (build it first: bun run build:maps)
bun run cli.ts maps "dental clinic" "Bristol" --limit 20

# Enrich a company website: emails, socials, decision makers, short summary
bun run cli.ts enrich https://example.com --title "Example Ltd" --mode fast

# Enrich many leads at once from a JSON array of {title, website}
bun run cli.ts enrich-batch leads.json --concurrency 3 -o enriched.json

# Audit a site: SEO checklist, conversion channels, services, digital maturity
bun run cli.ts audit https://example.com

# Audit + Maps competitor review + deterministic growth plan (--locale en for English)
bun run cli.ts intel --site https://example.com --niche "dental clinic" --loc Bristol --limit 3

# Discover -> enrich -> draft outreach copy -> JSONL (or .csv). Draft only, nothing is sent
bun run cli.ts gtm --niche "dental clinic" --loc Bristol --limit 5 --out leads.jsonl

# Lint copy for AI-slop (argument, --file, or stdin)
bun run cli.ts antislop "No cenΓ‘rio atual, uma soluΓ§Γ£o revolucionΓ‘ria"

# Score buying intent of a post or comment (generic lexicon; --vertical car for vehicles)
bun run cli.ts intent "Procuro um sofΓ‘ atΓ© R$ 2.500"

# Public social lookups, no keys: profile meta tags and Reddit search
bun run cli.ts social-lookup https://www.instagram.com/example/
bun run cli.ts intent-search "recommend a dentist Goiania" --subreddit goiania

# Run the Maps scraper as a local service (127.0.0.1:8088); `maps`, `gtm` and `intel` use it when up
bun run cli.ts daemon start
bun run cli.ts daemon status
bun run cli.ts daemon stop

# Start MCP Server via SSE on port 3000
bun run cli.ts serve --transport sse --port 3000

Behind a TLS-intercepting proxy? Export LOOKACRAWLER_INSECURE_TLS=true to accept the proxy's forged certificate. Off by default β€” never enable it for untrusted networks.

Rotating proxies? Export LOOKACRAWLER_PROXIES with a comma or whitespace separated list of URLs. Every request without an explicit --proxy pulls the next entry, so one blocked IP is not fatal for the run.

Local proxy (Tor, mitmproxy, a sidecar)? A proxy passed per request must be a public host. List trusted local proxies in LOOKACRAWLER_ALLOWED_PROXIES (comma separated, exact URLs); entries in LOOKACRAWLER_PROXIES are trusted too.

SSE server security

Variable

Effect

LOOKACRAWLER_SSE_TOKEN

Bearer token required on every request. If the server is bound to a non-loopback address (e.g. --host 0.0.0.0) and this is unset, a random token is generated and printed at startup.

LOOKACRAWLER_SSE_ALLOWED_ORIGINS

Comma-separated web origins allowed to call the server from a browser (CORS). Requests with any other Origin header are refused. CLI/desktop MCP clients are unaffected.

LOOKACRAWLER_SSE_ALLOW_UNAUTHENTICATED

true disables the token requirement on non-loopback binds. Only for isolated networks.

LOOKACRAWLER_SSE_MAX_SESSIONS

Maximum concurrent SSE clients (each gets its own MCP session). Default 16; further connections get 503 until one disconnects.

LOOKACRAWLER_MAX_BROWSERS

Maximum concurrent Chromium processes (one per distinct proxy). Default 4; idle ones are closed after LOOKACRAWLER_BROWSER_IDLE_MS (default 120000).

Every outbound connection goes through a built-in loopback egress guard that resolves each destination once, refuses private/link-local/loopback addresses and connects to exactly the IP it checked. This covers redirects and requests a page makes on its own (fetch, XHR, WebSocket) in deep mode, and prevents DNS rebinding. With a proxy (--proxy, LOOKACRAWLER_PROXIES) the guard sits in front of it: it validates the destination, then asks the proxy to connect to that IP (HTTP CONNECT, SOCKS5 with optional user/password, or SOCKS4), so a proxy β€” even a trusted local one β€” can never be steered at an internal host. Side effect: DNS is resolved on this machine, not at the proxy, so geo-DNS/CDN edges follow your location rather than the proxy's, and SOCKS4 cannot reach IPv6-only sites. LOOKACRAWLER_ALLOW_LOCAL=true turns all of this off and talks to the proxy directly (for local development only).

3. Google Maps engine (optional)

The maps command, daemon, gtm, intel and the discover_local_leads MCP tool drive a Google Maps scraper written in Go. Its source lives in google-maps-scraper/ (MIT, originally by Georgios Komninos (gosom), via coelhobugado/google-maps-scraper, with local fixes for hangs and leaked browsers).

Responsible use. Google's Maps Platform terms restrict scraping Google Maps content. Use this engine for low-volume research you review yourself, respect each site's terms, and prefer the official Places API for commercial volume. Build it once (needs Go 1.26+; install-browser also needs Node.js 18+; the Docker image ships it built):

bun run build:maps
cd google-maps-scraper && ./maps-leads install-browser   # first run only

The binary is looked up next to cli.ts, in ../google-maps-scraper/, or at $MAPS_LEADS_BIN (an explicit path that does not exist is an error, not a fallback).

Without it, maps fails fast with a clear message; extract, crawl, contacts, places and enrich are unaffected. Pass --email to let the scraper extract public emails during discovery.

4. Docker Deployment

# Build and run Docker container
docker build -t lookacrawler .
docker run -p 3000:3000 -e LOOKACRAWLER_SSE_TOKEN="$(openssl rand -hex 24)" lookacrawler

The container listens on 0.0.0.0, so a token is always required. Without LOOKACRAWLER_SSE_TOKEN a random one is generated on each start and printed in the container logs.


πŸ§ͺ Architecture & Testing

Incoming URL ──► [Local SQLite Cache Check] ──(Hit)──► Return Cached Markdown
                       β”‚ (Miss)
                       β–Ό
            [Fast HTTP GET Request] ──(Blocked?)──► [Escalate to Browser Rendering]
                       β”‚                                      β”‚
                       β–Ό                                      β–Ό
            [HTML DOM Tree Parser] β—„β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                       β”‚
                       β–Ό
       [Aggressive Token Noise Pruner]
       (Strips SVG, Nav, Ads, Tracking, CSS, JS)
                       β”‚
                       β–Ό
         [Mozilla Readability Engine]
                       β”‚
                       β–Ό
         [Turndown Markdown Converter] ──► Return Clean LLM Markdown

Run test suite:

bun test

⭐ Star & Support

If LookaCrawler saves you API fees and token costs:

  • ⭐ Star this repository to help other developers find it!

  • πŸ’‘ Open an Issue / PR for rendering improvements or crawler features.


Built by LookADev

lookacrawler is built and maintained by LookADev, an engineering studio specializing in AI agents, web architecture, and token optimization.

Start a project β†’ lookadev.com Β· Email: lucas@lookadev.com

πŸ“„ License

Open-source software licensed under the MIT License.

Available Tools

9 tools
batch_extract_web_contentA

Batch extract token-optimized Markdown from multiple website URLs concurrently, with aggregate token statistics.

What it does Runs the same fast/deep pipeline as extract_web_content across an array of up to 20 URLs in parallel, then returns per-URL results plus a summary (urls attempted, succeeded, failed, total tokens, and per-page token counts).

How to use

  • Use when you need many pages at once β€” docs, a list of product pages, a set of sources to compare.

  • mode applies to every URL. concurrency (1-10) caps parallel workers; keep it modest on fast machines / low bandwidth.

  • css_selector is applied to all URLs. headers/cookies/proxy apply globally to every request.

  • Each URL is independent: a single failure does not abort the batch (results carry an "error" field for that URL).

Returns Structured JSON with per-url markdown/tokens/error and aggregate totals. Incomplete or empty batches still return a valid result object.

Inputs: urls (required), mode, proxy, cookies, +4 more.

crawl_websiteB

Recursively crawl an entire website or documentation section with depth limits, URL pattern filtering, and token accounting.

Inputs: start_url (required), mode, max_depth, max_pages, +4 more.

deep_enrich_leadB

Deeply enrich a business lead by crawling its official website with LookaCrawler's token-optimized engine. Extracts verified emails, social media links (Instagram, LinkedIn), decision makers / founders, and generates a concise Markdown summary (<300 tokens) for LLMs.

Inputs: title (required), website (required), mode, phone, +4 more.

discover_local_leadsA

Discover local businesses, establishments, and B2B prospects using the Google Maps engine. Extracts title, category, formatted address, telephone, WhatsApp link, rating, review count, coordinates, and website URL.

Inputs: query (required), lang, limit, location.

extract_contactsA

Extract verified contact information (emails, phone numbers, WhatsApp links, and social media profiles) from a website and its contact subpages. Drastically saves tokens compared to feeding the entire raw DOM to the LLM.

Inputs: url (required), deep_scan.

extract_structured_dataA

Extract structured JSON β€” page metadata (Open Graph, canonical URL, author, dates) and/or a custom CSS-selector schema β€” from a website.

What it does Fetches a URL and returns a structured object. With include_metadata=true it reads Open Graph tags (og:title, og:description, og:image), the canonical URL, author, and publication/modified dates. You can also pass a schema (property name -> CSS selector) to pull specific fields (e.g. {"title": "h1", "price": ".price", "rating": "span.rating"}) into a typed object.

How to use

  • Use for product listings, news/metadata, schema-driven extraction, and any time you need fields instead of prose.

  • schema keys become the JSON keys; values are CSS selectors. Leave schema empty to get metadata only.

  • include_metadata (default true) adds the Open Graph / author / date block. Set false for a lean result.

  • mode/css_selector/headers/cookies/proxy behave exactly as in extract_web_content.

Returns JSON object with the requested fields (and/or metadata). Missing selectors are omitted rather than failing the whole call. Non-http or private URLs fail with isError: true.

Inputs: url (required), mode, proxy, schema, +5 more.

extract_web_contentA

Extract token-optimized, clean Markdown content from a target website for LLM consumption.

What it does Fetches a URL, strips HTML bloat (scripts, styles, inline SVGs, tracking tags, navigation, footers, redundant forms) and returns readable Markdown β€” cutting token usage by ~73% to 90% versus the raw page.

How to use

  • Use for any web page, article, or docs you want as LLM-ready text.

  • mode="fast" (default): native HTTP GET. mode="deep": headless Chrome with stealth fingerprint for JS-heavy or Cloudflare/Turnstile-protected pages.

  • css_selector scopes to a single element (e.g. "main", "article", "#content").

  • Pass headers/cookies for gated or geo-restricted content. Providing any of headers/cookies/proxy bypasses the SQLite cache.

  • No auth required. Respects robots/rate-limit via retry backoff.

Returns Markdown text. Cache hits are prefixed with a NOTE marker. Unsupported URLs (non-http, private IP, SSRF) fail with isError: true and a reason.

Inputs: url (required), mode, proxy, actions, +6 more.

map_websiteA

Discover the architecture and page inventory of a website domain via sitemaps, robots.txt, and link graphs. Returns a list of URLs with source and modification metadata. Useful for exploring a site before targeted crawling.

Inputs: url (required), max_links.

search_placesA

Search for local businesses, places, and establishments on Google Maps, extracting structured entity data (title, address, phone, website, coordinates, rating).

Inputs: query (required), limit.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.7/5.0

    Scored across 9 tools

    Disambiguation3/5

    Most tools target distinct actions, but two near-duplicate pairs stand out: discover_local_leads vs search_places (both pull the same Google Maps entity fields), and extract_contacts vs deep_enrich_lead (both crawl a business site for emails/socials). Descriptions add some differentiation, but an agent could easily misselect within these pairs.

    Naming Consistency5/5

    All names are snake_case and follow a verb_noun pattern (discover_local_leads, extract_contacts, crawl_website, map_website, search_places). Minor compounds like deep_enrich_lead and batch_extract_web_content are still readable and consistent with the convention.

    Tool Count5/5

    Nine tools is well within the sweet spot for a crawling/scraping server, and each tool covers a distinct capability tier (discovery, extraction, enrichment, batch, site mapping). No obvious padding or redundancy-driven bloat.

    Completeness4/5

    The surface covers the full lead-gen lifecycle: place discovery, contact extraction, lead enrichment, content/markdown extraction, recursive crawl, batch, structured extraction, and sitemap discovery. The main gap is a lack of a status/polling or pagination/continuation operation for long-running crawls or large result sets.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Open-source web scraper and extraction MCP server with JavaScript rendering, markdown output, PDF/DOCX parsing, structured errors, and validated extraction contract diagnostics for agents.
      2
      AGPL 3.0
    • A
      license
      A
      quality
      B
      maintenance
      A fault-tolerant, stealth-enabled Model Context Protocol (MCP) server for web searching and content fetching. Built for AI Agents (Cursor, Claude Code, OpenCode), it uses a stealth browser engine to fetch pages, dynamically handles SPAs/React, and converts bloat into token-optimized Markdown.
      2
      28 npm
      51 PyPI
      4
      MIT

    Appeared in Searches