JavaScript SDK

A lightweight, zero-dependency client for the CrawlKit API. Uses the standard fetch API — works in Node.js 18+, Deno, Bun, and modern browsers.

No installation required. These examples use the native fetch API. Copy-paste into any JavaScript project and start making API calls immediately.

Client Setup

const CRAWLKIT_API_KEY = "ck_live_YOUR_API_KEY";
const BASE_URL = "https://api.crawlkit.app/api/v1";

async function crawlkit(method, path, body = null, params = {}) {
  const url = new URL(`${BASE_URL}${path}`);
  Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));

  const res = await fetch(url.toString(), {
    method,
    headers: {
      "Authorization": `Bearer ${CRAWLKIT_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: body ? JSON.stringify(body) : undefined,
  });

  if (!res.ok) {
    const err = await res.json();
    const error = new Error(err.message || `HTTP ${res.status}`);
    error.status = res.status;
    error.retryable = err.retryable || false;
    error.retryAfter = err.retry_after;
    throw error;
  }

  return res.json();
}

Data Platform Examples

Create a Dataset

// Create a dataset for product catalog data
const dataset = await crawlkit("POST", "/datasets", {
  name: "product_catalog",
  description: "E-commerce product data scraped from competitor sites",
  columns: [
    { name: "product_name", data_type: "text" },
    { name: "price", data_type: "float" },
    { name: "category", data_type: "text" },
    { name: "in_stock", data_type: "boolean" },
    { name: "specs", data_type: "jsonb" },
    { name: "scraped_at", data_type: "timestamp" },
  ],
});

console.log(`Dataset created: ${dataset.id}`);

Add Rows to a Dataset

// Insert rows from your application
const result = await crawlkit("POST", `/datasets/${dataset.id}/rows`, {
  format: "json",
  data: [
    {
      product_name: "Wireless Keyboard",
      price: 79.99,
      category: "Electronics",
      in_stock: true,
      specs: { connectivity: "Bluetooth 5.0", battery: "6 months" },
    },
    {
      product_name: "USB-C Hub",
      price: 49.99,
      category: "Electronics",
      in_stock: true,
      specs: { ports: 7, power_delivery: "100W" },
    },
  ],
});

console.log(`Inserted ${result.inserted} rows`);

Deploy a Spider

// Create a spider to extract pricing data from a competitor
const spider = await crawlkit("POST", "/spiders", {
  name: "competitor_pricing",
  scope: {
    start_urls: ["https://books.toscrape.com/catalogue/category/books/travel_2/index.html"],
  },
  definition: {
    handlers: [
      {
        url_pattern: "/products/*",
        fields: [
          { name: "product_name", selector: "h1.product-title", type: "text" },
          { name: "price", selector: ".current-price", type: "text" },
          { name: "category", selector: ".breadcrumb li:last-child", type: "text" },
          { name: "in_stock", selector: ".stock-status", type: "text" },
          { name: "image_url", selector: "img.product-hero", type: "attribute", attribute: "src" },
        ],
      },
    ],
    navigation: {
      follow_links: ".pagination a",
      max_depth: 3,
    },
  },
  dataset_id: dataset.id,
});

console.log(`Spider ${spider.id}: ${spider.status}`);

Run Enrichment

// Enrich a dataset with company intelligence
const job = await crawlkit("POST", "/enrichment/enrich", {
  dataset_id: dataset.id,
  source_name: "company_data",
  input_mapping: { url: "domain" },
  output_mapping: {
    company_name: "company",
    employee_count: "employees",
    industry: "industry",
  },
});

console.log(`Enrichment ${job.job_id}: ${job.status}`);

// Poll for completion
let status = job;
while (status.status === "running" || status.status === "pending") {
  await new Promise((r) => setTimeout(r, 5000));
  status = await crawlkit("GET", `/enrichment/jobs/${job.job_id}`);
  console.log(`Progress: ${status.processed_rows}/${status.total_rows}`);
}

console.log(`Enrichment complete: ${status.status}`);

Create and Run a Pipeline

// Build a multi-step data pipeline
const pipeline = await crawlkit("POST", "/pipelines", {
  name: "lead_generation_pipeline",
  steps: [
    {
      type: "crawl",
      config: { spider_id: spider.id, max_pages: 1000 },
    },
    {
      type: "enrich",
      config: {
        source_name: "tech_stack_detector",
        input_mapping: { url: "domain" },
        output_mapping: { technologies: "tech_stack" },
      },
    },
    {
      type: "filter",
      config: {
        conditions: [
          { field: "tech_stack", operator: "contains", value: "React" },
        ],
      },
    },
    {
      type: "export",
      config: { format: "json", destination: "webhook", webhook_url: "https://your-app.com/api/leads" },
    },
  ],
});

// Execute the pipeline
const run = await crawlkit("POST", `/pipelines/${pipeline.id}/run`);
console.log(`Pipeline run started: ${run.run_id}`);

SEO Analysis Examples

Check a URL

// Ship code that Google actually indexes
const check = await crawlkit("POST", "/check-url", {
  url: "https://crawlkit.app",
  js_rendering: false,
});

console.log(`Score: ${check.score}/100`);
console.log(`Issues found: ${check.issues.length}`);

// Show critical and high severity issues
check.issues
  .filter((i) => i.severity === "critical" || i.severity === "high")
  .forEach((issue) => {
    console.log(`[${issue.severity.toUpperCase()}] ${issue.message}`);
  });

Run a Site Audit

const audit = await crawlkit("POST", "/audit/run", {
  site_url: "https://crawlkit.app",
  max_pages: 50,
  js_rendering: false,
  include_link_analysis: true,
});

console.log(`Audit ${audit.audit_id}`);
console.log(`Score: ${audit.score}/100`);
console.log(`Pages crawled: ${audit.crawl_stats.pages_crawled}`);
console.log(`Issues: ${audit.issues.length}`);

Error Handling with Retry Logic

async function crawlkitWithRetry(method, path, body = null, options = {}) {
  const maxRetries = options.maxRetries || 3;
  const baseDelay = options.baseDelay || 1000;

  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      return await crawlkit(method, path, body);
    } catch (err) {
      const isLast = attempt === maxRetries;
      const isRetryable = err.retryable && !isLast;

      if (!isRetryable) {
        throw err;
      }

      // Use server-provided delay or exponential backoff
      const delay = err.retryAfter
        ? err.retryAfter * 1000
        : baseDelay * Math.pow(2, attempt) + Math.random() * 500;

      console.warn(`Retry ${attempt + 1}/${maxRetries} in ${Math.round(delay)}ms`);
      await new Promise((r) => setTimeout(r, delay));
    }
  }
}

// Usage
const result = await crawlkitWithRetry("POST", "/check-url", {
  url: "https://crawlkit.app",
});

Browser Usage

CORS note: The CrawlKit API supports CORS for browser-based requests. However, never expose your API key in client-side code. Use a backend proxy to keep your key secure.
// Proxy through your backend to protect the API key
async function checkUrl(url) {
  const res = await fetch("/api/crawlkit/check-url", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ url }),
  });
  return res.json();
}

// Your backend (e.g., Express or Next.js API route)
app.post("/api/crawlkit/check-url", async (req, res) => {
  const result = await crawlkit("POST", "/check-url", {
    url: req.body.url,
  });
  res.json(result);
});
PreviousTypeScript SDK NextPython SDK