A crawler for AI agents.
Crawl, watch, keep it fresh.

Your agent can already search. Marrow is for the next step — get the data, watch it, and know exactly what changed. Section-level change tracking, flat-rate monitoring.

$ npx -y marrow-setup --email you@example.com
Marrow

Your agent already searches. So why Marrow?

👁️

It watches for changes

Search can't tell you what changed. Marrow can. Tracks additions, modifications, moves and removals — section by section.

📦

Clean data, not snippets

Marrow returns clean markdown — humans can read it, and so can your AI.

🪙

Token-efficient & cheap

Scout → read: marrow_scout maps a page's links and structure, then marrow_read deep-reads it — fewer tokens burned. Cache is standard, so the second read is fast and cheap. Monitoring is flat-rate.

Building RAG pipelines? Each section gets a stable id — vector DB upsert works out of the box.

Usage

1 · Scout, then read

Say "search with Marrow" and marrow_scout + marrow_read pull clean markdown.

2 · Change tracking

Ask your AI to check a URL for updates and get a section-level diff versus your last read — the diff is free.

3 · Do your rounds

Keep a watchlist in a skill and just tell your AI "do today's rounds."

Stop hauling the dirt. Get the marrow.

Most crawlers bulldoze through the whole rendered page — navs, ads, footers, related-product carousels and all. Marrow goes for the marrow: it pulls the essence from the page's backend (the source JSON) and uses the rendered frontend only to verify. You get the nutritious core, not the bone. That's the whole point of the name.

PageTokens vs Firecrawl — same URL
Clean article (Wikipedia)On par — little chrome to strip
News article (BBC)~30% fewer
Heavy e-commerce (Shopify product)~75% fewer
The product feed behind that pageup to 26× smaller

The more clutter, the bigger the win. Measured head-to-head between Firecrawl and Marrow on the same URLs. And that's per pagescout → read saves even more tokens by skipping pages you don't need. (When a page exposes no backend JSON, Marrow falls back to markdown from the rendered frontend.)

Watch it. Frequency is free.

Firecrawl bills monitoring per check — 1 credit per page, every time, so the bill climbs with every URL and every interval. Marrow is flat-rate. Check as often as you want — it costs nothing.

You

Do my morning rounds — only tell me what changed.

Your agent · Marrow

Checked the 5 pages in your watchlist. Two moved:

  • competitor-a.com/pricing — Pro plan $49$39 1 section modified
  • rival.io/careers — two senior backend roles posted 2 sections added

The other three are unchanged since yesterday.

Your watchlist lives in a skill and you just ask. Each read is one credit; checking a few times a day barely touches your plan.

Want it hands-off? Monitor + Webhook.

Register a URL and Marrow checks it on schedule — fires a webhook when something changes. No dashboard, no wiring. Flat-rate; checks don't count.

Worked example: monitoring 100 pages every 30 min = ~144,000 checks/month.

ItemFirecrawlMarrow
Billed asper-check (1 / page / check)flat — checks don't count
Plan you needGrowth (Standard's 100k credits won't cover it)Pro — 100 monitors
Cost$333 / mo$29.99 / mo — ~11× cheaper

Crank the interval to every 5 minutes — same price. Webhooks are signed and Firecrawl-compatible. (Firecrawl prices are their listed plans.)

What you scrape stays yours.

The URLs you watch are your strategy — competitor prices, hiring pages, policy changes. That's not for a crawler to know. Marrow is built so there's nothing to leak.

🔑

No account, no password

Your API key is your identity — like gh auth or stripe login. Nothing to sign up for, nothing to phish. Throw the key away and you're gone.

💳

Billing: Stripe

Card details go straight to Stripe — Marrow never sees them, and never stores your name or address. All we hold is an email handle and a credit balance.

🙈

No activity log

The extraction worker is stateless and the cache is content-addressed — it records that a page exists, not who asked for it. There's no dashboard of every URL you've ever pulled.

Most crawlers keep exactly that dashboard. Your watchlist is a trade secret — Marrow doesn't hold it.

Install in your agent

One command — it gets you a free key and wires Marrow into every agent you use.

$ npx -y marrow-setup --email you@example.com

Or configure it manually

claude mcp add marrow \
  -e MARROW_API_KEY=mrw_xxx \
  -- npx -y @marrowdev/mcp
{
  "mcpServers": {
    "marrow": {
      "command": "npx",
      "args": ["-y", "@marrowdev/mcp"],
      "env": { "MARROW_API_KEY": "mrw_xxx" }
    }
  }
}
# ~/.codex/config.toml
[mcp_servers.marrow]
command = "npx"
args = ["-y", "@marrowdev/mcp"]
env = { MARROW_API_KEY = "mrw_xxx" }

Tools: marrow_scout · marrow_read · marrow_search · marrow_crawl · marrow_screenshot · marrow_monitor_*

Or call the API

Plain HTTP with a Bearer key. The REST API is Firecrawl-compatible.

import requests

BASE = "https://api.marrow.navii.online"
H = {"Authorization": "Bearer mrw_xxx", "Content-Type": "application/json"}

# Scrape + change tracking → also get a chunk-level diff vs last time
r = requests.post(f"{BASE}/v1/scrape", headers=H, json={
    "url": "https://example.com/pricing",
    "formats": ["markdown", "changeTracking"],
})
ct = r.json()["data"]["changeTracking"]
print(ct["changeStatus"])          # new / same / changed
for c in ct["chunks"]:             # the delta
    print(c["status"], c["anchor"])

# Watch it: flat-rate monitor → webhook on change
requests.post(f"{BASE}/v1/monitor", headers=H, json={
    "url": "https://example.com/pricing",
    "interval_minutes": 30,
    "webhook_url": "https://you.example/hook",
})
const BASE = "https://api.marrow.navii.online";
const H = { Authorization: "Bearer mrw_xxx", "Content-Type": "application/json" };

// Scrape + change tracking
const res = await fetch(`${BASE}/v1/scrape`, {
  method: "POST", headers: H,
  body: JSON.stringify({
    url: "https://example.com/pricing",
    formats: ["markdown", "changeTracking"],
  }),
});
const { data } = await res.json();
console.log(data.changeTracking.changeStatus);   // new / same / changed
for (const c of data.changeTracking.chunks) {
  console.log(c.status, c.anchor);               // the delta
}

// Watch it
await fetch(`${BASE}/v1/monitor`, {
  method: "POST", headers: H,
  body: JSON.stringify({
    url: "https://example.com/pricing",
    interval_minutes: 30,
    webhook_url: "https://you.example/hook",
  }),
});
# Scrape + change tracking
curl -X POST https://api.marrow.navii.online/v1/scrape \
  -H "Authorization: Bearer mrw_xxx" -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/pricing","formats":["markdown","changeTracking"]}'

# Watch it
curl -X POST https://api.marrow.navii.online/v1/monitor \
  -H "Authorization: Bearer mrw_xxx" -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/pricing","interval_minutes":30,"webhook_url":"https://you.example/hook"}'

Coming from Firecrawl?

The REST API is drop-in compatible — point your client at Marrow, keep your code. changeTracking works the same.

CapabilityFirecrawlMarrow
CacheNoneStandard — re-reads ~free (0.1 cr)
Change trackingPage-level diffChunk-level + stable ids → vector upsert
MonitoringPer-check creditsFlat-rate — check as often as you want
Token useFull markdown dump30–75% fewer tokens — measured (back-of-page extraction + scout→read)
PrivacyAccount + activity dashboardNo account — key is identity, queries not logged
MigrationDrop-in: change the base URL

Free key, no card — start testing with npx marrow-setup in seconds.

Pricing

Plan Monthly credits Concurrent monitors Daily rate
Free · $05001100 / dayStart free
Developer · $9.995,000102,000 / daySubscribe
Pro · $29.9950,00010020,000 / daySubscribe

scrape/search 1 · scout 0.5 · crawl 2/page · screenshot 2 · Cache-hit 0.1 credits. Failed requests are free. Monitoring is flat — no per-check charge.