Skip to content

Find a component

Loading the directory…

↑ ↓ to select · Enter to open · Esc to closeBrowse all →
Contributor login

Firecrawl Scrape

A Bijection component for scraping web pages using the Firecrawl API with durable caching and reactive queries.

Bijection source
git clone https://github.com/bijectionhq/firecrawl-scrape.git
cd firecrawl-scrape
git checkout 2a73f77045c9756d5200b4c86e2559415d83cd6f

Bijection repository access is required. Request access.

Description

A Bijection component for scraping web pages using the Firecrawl API with durable caching and reactive queries.

Explore the package README for API concepts, configuration, and examples. Check the Bijection source for adaptation-specific setup.

Available as a reference

Review the source and its dependencies before adopting this package. Source availability does not establish npm publication or runtime qualification.

Getting started

  1. Get the source at the revision above and read its package documentation.
  2. Check the required Bijection SDK version, dependencies, and external service credentials.
  3. Follow the package setup instructions and the guide to using components.
  4. Exercise the component in your deployment according to your project’s verification rules.

Open source

Maintained source: bijectionhq/firecrawl-scrape. Based on Gitmaxd/convex-firecrawl-scrape. License: Apache-2.0. Consult the repository for license terms, notices, and contributor attribution.

From the upstream publisher

A Convex component for scraping web pages using the Firecrawl API with durable caching and reactive queries.

Explore the demo ↗

Upstream overview

From the upstream package documentation.

This component provides a durable web scraping service that extracts content from URLs and returns clean markdown, HTML, screenshots, or structured JSON data. Built on Firecrawl's scraping API, it features intelligent caching with configurable TTL, reactive status updates via Convex subscriptions, and built-in SSRF protection. The component handles async scraping jobs and stores results in your Convex database for reliable access.

Use cases

From the upstream package documentation.

  • Content aggregation apps that need to scrape blog posts, news articles, or documentation sites and convert them to clean markdown for display or processing
  • Product monitoring dashboards that extract structured data from e-commerce pages using JSON schemas to track pricing, availability, and product details
  • Research tools that capture screenshots and full HTML content from web pages for archival, comparison, or analysis workflows
  • AI training pipelines that need to scrape and clean web content at scale, with durable caching to avoid re-scraping the same URLs
  • Competitive intelligence platforms that monitor competitor websites and extract specific data points using schema-based extraction

How it works

From the upstream package documentation.

The component wraps Firecrawl's scraping API in Convex actions and provides a secure exposeApi() function that enforces authentication before any scraping operation. When you call scrape(), it starts an async job and returns a job ID that you can use with useQuery() to reactively monitor status updates.

Scraped content gets cached in your Convex database with a configurable TTL (default 30 days) and uses superset matching where cached results with multiple formats can satisfy requests for fewer formats. The component supports multiple output formats including markdown, HTML, screenshots, and AI-generated summaries, plus structured JSON extraction via schema validation.

All scraping operations include built-in SSRF protection that blocks private IPs and localhost, and the required auth wrapper ensures your Firecrawl API key stays secure. You can configure proxy options for anti-bot protection and set wait times for dynamic content rendering.

Use with agents and CLI

Give your coding agent the component’s source identity and setup guidance.

agent-prompt.md
Help me integrate Firecrawl Scrape with Bijection.

Read: https://bijection.com/components/firecrawl-scrape/SKILL.md

Check SDK compatibility and dependency availability.
Follow this project's execution and verification rules.

Upstream README.md

View repository ↗

Documentation from Gitmaxd/convex-firecrawl-scrape, recorded October 23, 2026. APIs and setup may differ in the Bijection adaptation.

Convex Firecrawl Scrape Component

Scrape any URL and get clean markdown, HTML, screenshots, or structured JSON - with durable caching and reactive queries.

const { jobId } = await scrape({ url: "https://example.com" });
// Status updates reactively as the scrape completes
const status = useQuery(api.firecrawl.getStatus, { id: jobId });
  • Durable caching with configurable TTL (default 30 days)
  • Reactive status updates via Convex subscriptions
  • Multiple output formats: markdown, HTML, raw HTML, screenshots, links, images, AI summaries
  • JSON extraction via schema-based LLM processing
  • Built-in SSRF protection blocks private IPs and localhost
  • Secure by default with required auth wrapper

Live Demo | Example Code

Play with the example:

git clone https://github.com/gitmaxd/convex-firecrawl-scrape.git
cd convex-firecrawl-scrape
npm install
npm run dev

Pre-requisite: Convex

You'll need an existing Convex project. Convex is a hosted backend platform with a database, serverless functions, and more. Learn more here.

Run npm create convex or follow any of the quickstarts to set one up.

Installation

npm install convex-firecrawl-scrape

Install the component in your convex/convex.config.ts:

// convex/convex.config.ts
import { defineApp } from "convex/server";
import firecrawlScrape from "convex-firecrawl-scrape/convex.config.js";

const app = defineApp();
app.use(firecrawlScrape);
export default app;

Set your Firecrawl API key:

npx convex env set FIRECRAWL_API_KEY your_api_key_here

Get your API key at firecrawl.dev.

Usage

Always use exposeApi() to expose component functionality. This wrapper enforces authentication and controls API key access.

// convex/firecrawl.ts
import { exposeApi } from "convex-firecrawl-scrape";
import { components } from "./_generated/api";

export const { scrape, getCached, getStatus, getContent, invalidate } =
  exposeApi(components.firecrawlScrape, {
    auth: async (ctx, operation) => {
      const identity = await ctx.auth.getUserIdentity();
      if (!identity) throw new Error("Unauthorized");
      return process.env.FIRECRAWL_API_KEY!;
    },
  });

React Integration

import { useMutation, useQuery } from "convex/react";
import { api } from "../convex/_generated/api";
import { useState } from "react";

function ScrapeButton({ url }: { url: string }) {
  const [jobId, setJobId] = useState<string | null>(null);
  const scrape = useMutation(api.firecrawl.scrape);
  const status = useQuery(
    api.firecrawl.getStatus,
    jobId ? { id: jobId } : "skip",
  );
  const content = useQuery(
    api.firecrawl.getContent,
    jobId && status?.status === "completed" ? { id: jobId } : "skip",
  );

  return (
    <div>
      <button
        onClick={async () => setJobId((await scrape({ url })).jobId)}
        disabled={status?.status === "scraping"}
      >
        {status?.status === "scraping" ? "Scraping..." : "Scrape"}
      </button>
      {status?.status === "completed" && <pre>{content?.markdown}</pre>}
      {status?.status === "failed" && <p>Error: {status.error}</p>}
    </div>
  );
}

Output Formats

const { jobId } = await scrape({
  url: "https://example.com",
  options: {
    formats: ["markdown", "html", "links", "images", "screenshot"],
    storeScreenshot: true,
  },
});
FormatDescription
markdownClean markdown content (default)
htmlCleaned HTML
rawHtmlOriginal HTML source
linksURLs found on the page
imagesImage URLs found on the page
summaryAI-generated page summary
screenshotScreenshot URL (use storeScreenshot: true to persist)

JSON Extraction

Extract structured data using a JSON schema:

const { jobId } = await scrape({
  url: "https://example.com/product",
  options: {
    extractionSchema: {
      type: "object",
      properties: {
        name: { type: "string" },
        price: { type: "number" },
      },
      required: ["name", "price"],
    },
  },
});

const content = await getContent({ id: jobId });
console.log(content.extractedJson); // { name: "Widget", price: 99.99 }

Cache Management

Cached results use superset matching: a cache entry with ["markdown", "screenshot"] satisfies a request for ["markdown"].

// Check cache
const cached = await getCached({ url: "https://example.com" });

// Force refresh
const { jobId } = await scrape({ url, options: { force: true } });

// Invalidate cache
await invalidate({ url: "https://example.com" });

Proxy Options

For anti-bot protected sites:

const { jobId } = await scrape({
  url: "https://protected-site.com",
  options: {
    proxy: "stealth", // Residential proxy
    waitFor: 3000, // Wait for dynamic content
  },
});

Security

Always use exposeApi() - never expose component functions directly to clients. Server-side code can call component internals directly, but doing so bypasses authentication. It ensures:

  • Authentication before any operation
  • API key controlled by your callback, not callers
  • Operation-specific authorization support
// ❌ DANGEROUS - bypasses auth
export const scrape = components.firecrawlScrape.lib.startScrape;

// ✅ SAFE - auth enforced
export const { scrape } = exposeApi(components.firecrawlScrape, { auth: ... });

SSRF Protection: Built-in validation blocks localhost, private IPs, and non-HTTP schemes.

For domain allowlists, rate limiting, and detailed security guidance, see docs/SECURITY.md.

Error Handling

const status = await getStatus({ id: jobId });
if (status?.status === "failed") {
  console.error(status.error, status.errorCode);
  // errorCode is the HTTP status or error code from Firecrawl (e.g., 402, 429, "BAD_REQUEST")
}

Found a bug? Feature request? File it here.

Advanced Usage

For configuration options, the FirecrawlScrape class API, and URL utilities, see docs/ADVANCED.md.

Development

npm install
npm run dev

License

Apache-2.0