Skip to content

Overview

#API & SDK

Use curl.md directly over HTTP or through the published TypeScript SDK.

#HTTP API

The simplest HTTP interface is the hosted curl.md/<url> path:

curl curl.md/developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch?objective=streaming+response+body&keywords=ReadableStream,getReader"

This is useful for quick integrations, shell scripts, and server-side fetches. The public /api surface also includes experimental routes for auth, API keys, organizations, invites, members, and more.

Browser shortcut

You can also use curl.md in your browser by adding curl.md/ in front of any URL. For example, curl.md/example.com

#TypeScript SDK

Use the curl.md npm package when you want a typed client in TypeScript.

#Install

Install curl.md with your favorite package manager:

npm i curl.md
Using Unreleased Commits

Commits are continuously released via pkg.pr.new and can be installed using the pull request number or short commit ID.

npm i https://pkg.pr.new/curl.md@123

When using unreleased commits, please keep in mind there can be breaking changes, especially for pull requests.

#Usage

Create a typed curl.md client, then call fetch with a URL and request options.

import { createClient } from 'curl.md'

const client = createClient()
const res = await client.fetch('docs.github.com/en/webhooks/webhook-events-and-payloads', {
  keywords: ['pull_request'],
  objective: 'pull request webhook event payload and actions',
})

const json = await res.json()

The SDK gives you typed access to request options like objective, keywords, mode, fresh, and token.

The lower-level client.api key exposes experimental /api routes directly.

#Request Options

Use these options with the HTTP API query string or the TypeScript SDK.

#objective

Use objective to narrow the response to content relevant to a specific goal. HTTP also accepts the aliases o and q.

#keywords

Use keywords to pre-filter the page before extraction. In HTTP, send them as a comma-separated string. HTTP also accepts the alias k.

#mode

Use mode to control the extraction model when objective is set. Supported values are smart and rush. HTTP also accepts the alias m.

#fresh

Use fresh to bypass cache and force a fresh fetch. In HTTP, you can send fresh=true or just include ?fresh. HTTP also accepts the alias f.

#token

Use token in the SDK to send an API key as a Bearer token. For raw HTTP requests, use the Authorization header instead.

#Authentication

Authenticated requests can use a Bearer token through the Authorization header.

#API Keys

For server-side apps, CI, and other non-interactive integrations, prefer an API key.

Create one from the CLI:

curl.md auth logincurl.md token create my-app

If you want an organization-scoped token, switch to that organization before creating it:

curl.md org switch acmecurl.md token create ci

Then send the token as a Bearer token over HTTP:

curl curl.md/example.com -H 'Authorization: Bearer curlmd_xxx'

Or pass it to the TypeScript SDK per request:

import { createClient } from 'curl.md'

const client = createClient()
const res = await client.fetch('example.com', {
  token: process.env.CURLMD_API_KEY,
})

API keys also work through the token or t query parameter when sending headers is inconvenient, though Authorization is recommended.

If you are using session-based auth instead of an API key and need to act within a specific organization, send x-organization-id as well.

#Response Format

The hosted HTTP endpoint returns markdown by default:

curl curl.md/example.com

That response uses text/markdown and returns the final markdown document directly.

If you prefer JSON, send Accept: application/json:

curl curl.md/example.com -H 'Accept: application/json'

The JSON shape is:

{
  "content": "# Example\n..."
}

#Response Headers

Successful fetch responses include useful metadata headers:

  • x-cache — whether the response was a cache HIT or MISS
  • x-request-id — request identifier for debugging
  • x-tokens-count — estimated token count for the final response
  • x-tokens-saved — estimated tokens saved versus the source content
  • x-cost-mills — request cost in mills
  • x-credits-remaining — remaining prepaid credits, when available

#Error Handling

Errors are returned as JSON with a stable string code and a human-readable message. Some errors include extra fields, like validation issues.

{
  "code": "invalid_api_key",
  "message": "Invalid API key"
}

In the TypeScript SDK, narrow on res.status before reading res.json(). That gives you endpoint-specific error types in TypeScript.

const res = await client.fetch('example.com')

switch (res.status) {
  case 200:
    return await res.json()
  case 400: {
    const json = await res.json()
    console.error(json.code) // "validation_error"
    return
  }
  case 502: {
    const json = await res.json()
    console.error(json.code) // "fetch_failed" | "ai_failed"
    return
  }
}

#Rate Limiting

On the main fetch endpoint, free usage is rate limited and returns 429 with code rate_limit_exceeded when exceeded.

  • Standard fetches: 100/hour anonymous, 1,000/hour authenticated
  • Objective queries: 3/hour anonymous, 10/hour authenticated
  • Paid usage skips these rate limits

Higher limits

Sign up for a free account for higher usage limits.

Successful responses include rate-limit headers:

  • x-ratelimit-limit
  • x-ratelimit-remaining
  • x-ratelimit-reset

Rate-limited responses also include retry-after.

#When to use the API/SDK

  • Use the HTTP API for quick fetches from browsers, scripts, and simple integrations.
  • Use the TypeScript SDK when you want typed request options and status-aware responses in app code. For example, tool plugins, like the OpenCode plugin and Pi extension.
  • Use the CLI when you want shell workflows, local auth, and token or organization management.