Skip to content
Skryp

Migrate from Firecrawl to Skryp

Skryp serves Firecrawl-shaped endpoints under /v2. Code written for Firecrawl's v2 API, including Firecrawl's own SDKs, works against Skryp when you change the API URL and the key. Every row below was called through the official SDKs on 1 October 2026; anything not listed is not supported.

Change two lines

With the Python SDK, keep your code and give the client Skryp's address and your Skryp key. This ran as shown:

migrate-firecrawl/01-firecrawl-sdk.py
# The official Firecrawl Python SDK, unchanged, pointed at Skryp: only the API URL and the key differ.
# pip install firecrawl-py    export SKRYP_API_KEY=...
import os

from firecrawl import Firecrawl

app = Firecrawl(api_key=os.environ["SKRYP_API_KEY"], api_url=os.environ.get("SKRYP_API_URL", "https://api.skryp.dev"))

doc = app.scrape("https://quotes.toscrape.com/", formats=["markdown", "links"])
print(f"scrape: {doc.metadata.title!r}, {len(doc.markdown)} characters of Markdown, {len(doc.links)} links")

site = app.map("https://books.toscrape.com/", limit=20)
print(f"map: {len(site.links)} URLs, first {site.links[0].url}")

found = app.search("books to scrape", limit=3)
print(f"search: {[r.url for r in found.web]}")

crawl = app.crawl("https://quotes.toscrape.com/", limit=3, poll_interval=2)
print(f"crawl: {crawl.status}, {len(crawl.data)} pages")

batch = app.batch_scrape(["https://quotes.toscrape.com/page/1/", "https://quotes.toscrape.com/page/2/"], formats=["markdown"], poll_interval=2)
print(f"batch scrape: {batch.status}, {len(batch.data)} pages")

usage = app.get_credit_usage()
print(f"credit usage: {usage.remaining_credits} credits remaining")
OutputRan 1 Oct 2026 · Python 3.12.14, firecrawl-py 4.45.1 · 7.7 s
scrape: 'Quotes to Scrape', 4239 characters of Markdown, 49 links
map: 20 URLs, first https://books.toscrape.com/index.html
search: ['https://books.toscrape.com/', 'https://toscrape.com/', 'https://github.com/kawsarlog/books-to-scrape-web-scraper']
crawl: completed, 3 pages
batch scrape: completed, 2 pages
credit usage: 20861 credits remaining

The JavaScript SDK works the same way:

migrate-firecrawl/03-firecrawl-js-sdk.mjs
// The official Firecrawl JavaScript SDK, unchanged, pointed at Skryp: only the API URL and the key differ.
// npm install @mendable/firecrawl-js    export SKRYP_API_KEY=...
import Firecrawl from "@mendable/firecrawl-js";

const app = new Firecrawl({ apiKey: process.env.SKRYP_API_KEY, apiUrl: process.env.SKRYP_API_URL ?? "https://api.skryp.dev" });

const doc = await app.scrape("https://quotes.toscrape.com/", { formats: ["markdown"] });
console.log(`scrape: ${JSON.stringify(doc.metadata.title)}, ${doc.markdown.length} characters of Markdown`);

const site = await app.map("https://books.toscrape.com/", { limit: 20 });
console.log(`map: ${site.links.length} URLs`);

const found = await app.search("books to scrape", { limit: 3 });
console.log(`search: ${found.web.map((r) => r.url).join(", ")}`);

const crawl = await app.crawl("https://quotes.toscrape.com/", { limit: 3, pollInterval: 2 });
console.log(`crawl: ${crawl.status}, ${crawl.data.length} pages`);
OutputRan 1 Oct 2026 · Node.js 24.16.0, @mendable/firecrawl-js 4.42.1 · 6.6 s
scrape: "Quotes to Scrape", 4239 characters of Markdown
map: 20 URLs
search: https://books.toscrape.com/, https://toscrape.com/, https://www.geeksforgeeks.org/python/scrap-books-using-beautifulsoup-from-books-toscrape-in-python/
crawl: completed, 3 pages

What was tested

Tested 1 October 2026

Through the official Python SDK (firecrawl-py 4.45.1) and JavaScript SDK (@mendable/firecrawl-js 4.42.1), against Skryp's preview service. Re-tested whenever the /v2 routes change.

Endpoint or optionStatusNotes
POST /v2/scrape: Markdown, links, HTML, raw HTML, images, screenshotTestedA screenshot comes back as a link to the image stored by Skryp.
POST /v2/scrape with a json format (prompt or schema)TestedRuns Skryp extraction; values are checked against the page.
Actions: wait, click, write, press, scroll, screenshotTestedRun as Skryp browser steps.
location.country, proxy: basic or enhancedTestedbasic uses our own network; enhanced a residential proxy in the country. The verified exit is in metadata.egress.
POST /v2/mapTested
POST /v2/searchTestedResults under data.web.
POST /v2/crawl, GET /v2/crawl/{id}, DELETE /v2/crawl/{id}Tested
POST /v2/batch/scrape, GET /v2/batch/scrape/{id}Tested
POST /v2/extract, GET /v2/extract/{id}TestedAn answer that is a list comes back under items.
GET /v2/team/credit-usageTestedShows your Skryp balance.
Change tracking, branding, summary and audio formatsNot supportedUse Skryp's monitor and extract instead.

Here is the second half of the test, as it ran:

migrate-firecrawl/02-formats-actions-extract.py
# The rest of the Firecrawl v2 surface through the official SDK: other formats, page actions, extract, cancel.
# pip install firecrawl-py    export SKRYP_API_KEY=...
import os
import re

from firecrawl import Firecrawl

app = Firecrawl(api_key=os.environ["SKRYP_API_KEY"], api_url=os.environ.get("SKRYP_API_URL", "https://api.skryp.dev"))
URL = "https://quotes.toscrape.com/"


def check(name, fn):
    try:
        print(f"ok    {name}: {fn()}")
    except Exception as e:  # report and carry on, so one gap does not hide the others
        print(f"FAIL  {name}: {type(e).__name__}: {str(e)[:160]}")


check("html", lambda: f"{len(app.scrape(URL, formats=['html']).html)} characters")
check("rawHtml", lambda: f"{len(app.scrape(URL, formats=['rawHtml']).raw_html)} characters")
check("images", lambda: f"{len(app.scrape('https://books.toscrape.com/', formats=['images']).images)} image URLs")
check("screenshot", lambda: app.scrape(URL, formats=["screenshot"]).screenshot[:40] + "…")
check("json with a prompt", lambda: app.scrape(URL, formats=[{"type": "json", "prompt": "The first quote's text and author"}]).json)
def page_two_by_click():
    doc = app.scrape(
        "https://quotes.toscrape.com/js/",
        formats=["markdown"],
        actions=[{"type": "wait", "milliseconds": 1000}, {"type": "click", "selector": "li.next a"}, {"type": "wait", "milliseconds": 1000}],
    )
    return f"after clicking Next the browser is on {doc.metadata.url}"


check("actions", page_two_by_click)
check("extract", lambda: app.extract(urls=[URL], prompt="The authors of the first three quotes").data)


def country():
    doc = app.scrape("https://ipinfo.io/json", formats=["markdown"], location={"country": "DE"}, proxy="enhanced")
    exit_ = doc.metadata.egress  # Skryp adds the verified exit to Firecrawl's metadata
    seen = re.search(r'"country": "(\w\w)"', doc.markdown).group(1)
    return f"exit {exit_['country'].upper()} (verified: {exit_['verified']}), and ipinfo.io saw a request from {seen}"


check("location.country + proxy=enhanced", country)


def start_and_cancel():
    job = app.start_crawl("https://books.toscrape.com/", limit=50)
    return f"crawl {job.id} cancelled: {app.cancel_crawl(job.id)}"


check("cancel crawl", start_and_cancel)
OutputRan 1 Oct 2026 · Python 3.12.14, firecrawl-py 4.45.1 · 12 s
ok    html: 10723 characters
ok    rawHtml: 10968 characters
ok    images: 20 image URLs
ok    screenshot: https://api.skryp.dev/v1/blob/32e376b76b…
ok    json with a prompt: {'quote_text': 'The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.', 'author': 'Albert Einstein'}
ok    actions: after clicking Next the browser is on https://quotes.toscrape.com/js/page/2/
ok    extract: {'items': [{'author': 'Albert Einstein'}, {'author': 'J.K. Rowling'}, {'author': 'Albert Einstein'}]}
ok    location.country + proxy=enhanced: exit DE (verified: True), and ipinfo.io saw a request from DE
ok    cancel crawl: crawl job_084d93666218 cancelled: True

Differences to know

  • Credits are Skryp credits. A standard request costs 1 credit, as a basic page does on Firecrawl. Heavier methods cost what they use: 5 credits through a residential proxy (10 with JavaScript rendering) and 25 for advanced unblocking, only when it succeeds; AI extraction adds 5. See Credits and prices.
  • Blocked pages cost nothing. Skryp charges 0 credits for a page it could not get past or could not load. A page that loads with an error status, such as a 404, costs its route's price on Skryp and 1 credit on Firecrawl; Firecrawl also charges 1 credit for a page that answers 403.
  • Every result says where it came from. Skryp adds metadata.egress (the exit's country, city and network, and whether it was verified) and metadata.creditsUsed to scrape results. See Receipts.
  • Strict country. Add strictCountry: true and a country request fails rather than quietly using another country.

Next steps