Skip to main content
Integrations/Migration / Jina Reader → fastCRW

Migrate from Jina Reader to fastCRW — URL-to-Markdown Upgrade Guide

Migrate from Jina Reader (r.jina.ai URL-prefix) to fastCRW POST /v1/scrape. Same clean markdown plus crawl, map, search, LLM extraction, JS rendering, and AGPL-3.0 self-hosting on a single Rust binary. Before/after code + endpoint mapping.

Published
May 22, 2026
Updated
May 22, 2026
Category
integrations
Verdict

Migrating from Jina Reader to fastCRW swaps the r.jina.ai URL-prefix call for a POST /v1/scrape request — you keep clean markdown output and gain crawl, map, search, LLM extraction, JS rendering, and AGPL-3.0 self-hosting.

Swap the r.jina.ai/<url> GET for a POST /v1/scrape with formats: ["markdown"]Keep clean LLM-ready markdown — fastCRW uses htmd, a Rust Turndown portGain crawl, map, search, and LLM extraction that Jina Reader does not offerSelf-host the AGPL-3.0 single Rust binary to remove rate limits entirely

Verdict

Migrating from Jina Reader to fastCRW takes about 30 minutes because fastCRW exposes a REST API on /v1/scrape that produces the same clean, LLM-ready markdown — you swap the r.jina.ai/<url> URL-prefix GET for a POST /v1/scrape with formats: ["markdown"]. It is a code change, not a pure base-URL swap, but the payoff is depth: crawl, map, search, LLM extraction, JavaScript rendering, and AGPL-3.0 self-hosting all become available.

This page is honest: Jina Reader is excellent at one-shot URL-to-markdown. You migrate when you need more than that.

Who this is for

  • Teams whose scraping outgrew one-shot URL-to-markdown — you now need to crawl sites, discover URLs, or run web search.
  • Teams hitting Jina Reader's rate limits — fastCRW self-hosting removes per-request limits entirely.
  • Teams with JavaScript-heavy targets — Jina Reader does not render JS; fastCRW auto-escalates to a headless browser.
  • Teams that require self-hosting — Jina Reader is proprietary with no on-prem option; fastCRW is AGPL-3.0.

If your use case is genuinely "one URL, get markdown, occasionally" — under ~100 requests/day — Jina Reader's dead simplicity is a real advantage and you may not need to migrate.

Before and after: GET prefix to POST scrape

Jina Reader's call is a GET with the target URL appended to r.jina.ai:

# Before — Jina Reader
import requests

url = "https://example.com"
response = requests.get(f"https://r.jina.ai/{url}")
markdown = response.text

fastCRW takes a POST with a JSON body, and the markdown comes back inside JSON:

# After — fastCRW
import requests

url = "https://example.com"
response = requests.post(
    "https://fastcrw.com/api/v1/scrape",
    headers={"Authorization": "Bearer fcrw_YOUR_KEY"},
    json={"url": url, "formats": ["markdown"]},
)
markdown = response.json()["markdown"]

For JavaScript-heavy pages that Jina Reader returns empty, request a renderer explicitly:

response = requests.post(
    "https://fastcrw.com/api/v1/scrape",
    headers={"Authorization": "Bearer fcrw_YOUR_KEY"},
    json={
        "url": url,
        "formats": ["markdown"],
        "renderer": "chrome",  # auto | http | lightpanda | chrome
    },
)

The Python SDK path is even shorter — pip install crw, then CrwClient().scrape(url, formats=["markdown"]).

Migration mapping table

This table maps Jina Reader's surface to its fastCRW equivalent and marks what Jina Reader does not do. (Endpoint surface verified 2026-05-22; re-verify the live route list before quoting.)

Jina Reader capabilityfastCRW equivalentMigration note
GET r.jina.ai/<url>POST /v1/scrape with JSON bodyRead result.markdown instead of response.text.
Markdown outputformats: ["markdown"]fastCRW uses htmd, a Rust Turndown port; test formatting parity.
(Jina Reader: markdown only)formats: ["html", "rawHtml", "links", "json"]fastCRW returns multiple formats from one call.
(no crawl in Jina Reader)POST /v1/crawlAsync → job id; poll GET /v1/crawl/:id. 1 credit per page.
(no URL discovery)POST /v1/mapReturns sitemap structure. 1 credit.
(no web search)POST /v1/searchSearXNG-backed. 1 credit per query.
(no structured extraction)formats: ["json"] + jsonSchemaLLM extraction via OpenAI + Anthropic. 5 credits via /v1/extract.
(no JS rendering)renderer paramauto, http, lightpanda, chrome.
Looping r.jina.ai for many URLsiterate /v1/scrape or use /v1/crawlThere is no /v1/batch/scrape.
(no MCP)built-in /mcp serverUsable from Claude Code, Cursor, Windsurf.
(no self-host — proprietary)AGPL-3.0 single Rust binarydocker run or run the binary directly.
(no screenshot)(not supported)formats: ["screenshot"] returns HTTP 422.
Auth headerAuthorization: Bearer fcrw_<key>Optional in self-host mode.

Step-by-step migration

The numbered steps below mirror the howToSteps schema for this page.

1. Locate every r.jina.ai call

Grep for r.jina.ai across your codebase. Note each call site and, importantly, where you read response.text as markdown — that read changes to result.json()["markdown"].

2. Choose cloud or self-host

For managed fastCRW, sign up at fastcrw.com and copy your fcrw_ key — the Free tier ships 500 one-time lifetime credits that never reset. To self-host the AGPL-3.0 build, run docker run -p 8080:8080 ghcr.io/us/crw:latest or the single static binary directly. Self-host needs no Redis, Node, or container orchestration.

3. Replace the GET with a POST

Swap requests.get(f"https://r.jina.ai/{url}") for requests.post(".../v1/scrape", json={...}). The target URL moves from the path into the JSON body's url field.

4. Request markdown and read the JSON field

Pass formats: ["markdown"] in the body, then read result.markdown from the JSON response. fastCRW uses htmd (a Rust Turndown port) — the output is semantically equivalent for LLM pipelines but test formatting on your pages.

5. Set a renderer for JS-heavy pages

For any pages Jina Reader returned empty because they are SPAs, set renderer to lightpanda or chrome. The default auto already escalates when it detects a framework-heavy or empty page.

Anywhere you previously looped r.jina.ai over a list of URLs, switch to /v1/crawl. For URL discovery use /v1/map; for web search use /v1/search. These collapse multi-call workarounds into one request.

7. Verify in the playground, then cut over

Test your target URLs in the playground, confirm the markdown matches what your pipeline expects, then flip production traffic.

What does not carry over

  • API shape differs. This is a code change, not a base-URL swap — GET becomes POST, path becomes JSON body, response.text becomes result.markdown.
  • No screenshot output. formats: ["screenshot"] returns HTTP 422.
  • No /v1/batch/scrape. For many URLs, iterate /v1/scrape concurrently or use /v1/crawl.
  • Stateless. No persistent browser sessions.
  • LLM extraction is OpenAI + Anthropic only.
  • fastCRW is heavier than Jina Reader's endpoint. You gain depth at the cost of Jina Reader's one-line simplicity — a deliberate trade.

Performance and pricing context

fastCRW's markdown comes from a real benchmark base: on Firecrawl's public scrape-content-dataset-v1 (1,000 URLs, 819 labeled; diagnose_3way.py, 2026-05-08) fastCRW reached 63.74% truth-recall of 819 labeled URLs with a p50 of 1914 ms across 3,000 requests and 0 errors. The honest tail is a p90 of 14157 ms — the disclosed cost of a chrome-stealth fallback that recovers hard URLs. Read the methodology before quoting.

On price, fastCRW is credit-based: scrape 1 credit (chrome 2), crawl 1/page, search 1/query, extract 5. The Free tier ships 500 one-time lifetime credits that never reset; Hobby is $13/mo launch (3k credits) and Standard $69/mo (100k). The AGPL-3.0 self-host build is $0 in license terms. Launch pricing ends 2026-06-01. For Jina Reader's current rates, check jina.ai.

Continue exploring

More from Integrations

View all integrations

Related hubs

Keep the crawl path moving