Use from your shell
From a terminal, a script, or CI, you use Marrow the way you’d use any HTTP API — curl the endpoints with your key. Building an agent instead? Wire the MCP server — it’s the same billed API behind agent-friendly tools.
Get a key
Section titled “Get a key”Free, no card, idempotent:
npx -y marrow-setup --email you@example.comThat saves a key to ~/.config/marrow/config.json (and wires up any agents you have). For shell use, put it in your environment:
export MARROW_API_KEY=mrw_xxxEverything below hits https://api.marrow.navii.online with the header Authorization: Bearer $MARROW_API_KEY.
Scrape a page
Section titled “Scrape a page”curl -s https://api.marrow.navii.online/v1/scrape \ -H "Authorization: Bearer $MARROW_API_KEY" -H "Content-Type: application/json" \ -d '{"url":"https://example.com/pricing"}'Returns clean markdown in data.data.body.
markdown is the only value formats serves today. Anything else is refused by name rather than ignored — if you ask for html you get told we do not have it, instead of a 200 carrying something we picked for you.
Two names are refused for a different reason, and get a different status:
| you ask for | you get | means |
|---|---|---|
html, or any name we never had | 400 unsupported formats: … | we do not have it — check the spelling |
changeTracking, sections | 410 monitoring-withdrawn | we had it and took it down — do not substitute another name |
When a read stops
Section titled “When a read stops”Every stop carries a name your code can match on, and a sentence for you. The name is in error, the sentence in note — they are never the same string, and the name is never wrapped in prose.
| status | error | means |
|---|---|---|
| 422 | nothing-extracted | we fetched the page and found nothing that reads as a body. Your request was fine. depth:"deep" may reach a rendering the cheap path cannot. |
| 400 | http-404, http-403, … | the site answered, and what it answered was that number |
| 424 | dns-failed | the host name did not resolve — nothing was fetched. A private-network-only name will never resolve from here. |
| 424 | unreachable | the host resolved but the connection never completed — nothing was fetched. |
| 400 | unsupported formats: … | see above |
| 410 | monitoring-withdrawn | see above |
Nothing extracted is not billed. No stop is — credits are only spent on reads that returned something.
⚠️ A read that finds nothing does not come back as a 200 with an empty body. That shape used to exist and was removed: a success carrying nothing is indistinguishable from a success carrying a page, right up until your parser finds no rows.
The 410 pair is frozen along with the rest of the monitoring lane while the extraction design is reworked. There is no date for their return.
formats picks a serialisation. depth picks the extractor. That split is worth knowing because only one of the two names sounds like it does that: formats:["markdown"] chooses how the document is written down, while depth decides which reader produced it — and the two readers do not agree, even on pages where rendering changes nothing. The sizes, the link counts and the first line all move. The measurement is here, and unifying the readers is open work.
Crawl, search, scout, screenshot
Section titled “Crawl, search, scout, screenshot”Same headers as above; just the body changes.
# crawl a site → clean pages (bounded) → data.pages[]curl -s …/v1/crawl -d '{"url":"https://docs.example.com","limit":25,"maxDepth":2}'
# web search via Marrow's private SearXNG → { results: [...] }curl -s …/v1/search -d '{"query":"rust async runtime"}'
# scout a page — links + structure, cheap (scout → read saves tokens) → data.links[]curl -s …/v1/scout -d '{"url":"https://example.com"}'
# full-page screenshot (PNG)curl -s …/v1/screenshot -d '{"url":"https://example.com"}'Watch a page — withdrawn
Section titled “Watch a page — withdrawn”/v1/monitor and everything under it answer 410 monitoring-withdrawn. Scheduled checks, webhooks and the stored snapshots are frozen while the extraction design is reworked; existing monitors are not running.
Check usage
Section titled “Check usage”curl -s https://api.marrow.navii.online/v1/usage -H "Authorization: Bearer $MARROW_API_KEY"# → { plan, credits_remaining, credits_used, credits_used_percent, daily_rate_limit, monitoring, … }# `monitoring` reads "monitoring-withdrawn" — that lane is frozen, not out of quota.Good to know
Section titled “Good to know”- Failed requests cost nothing. A cache hit costs ~0.1 credit; the first fetch of a URL is full price.
- Pipe JSON with
jq. Responses are JSON, socurl … | jq -r '.data.data.body'and friends compose cleanly. - Same API as the MCP server. The MCP server is this same API behind agent-friendly tools — both read the same key and bill the same way.
A native
marrowCLI (thin wrappers over these endpoints, formarrow scout | jq …-style pipelines) is on the roadmap. For now: curl, or the MCP server inside an agent.