Client libraries
Official clients for Python, JavaScript and TypeScript, Ruby and Go. Each is a thin layer over the HTTP API with typed results and errors, and the same behaviour in every language.
You don't need one: every endpoint is a single POST, and the code recipes show it in eight languages with nothing but an HTTP client. A library saves you the parts around that POST — retries, long analyses, error types and webhook signatures.
Install
| Language | Install | Package | Source | Notes |
|---|---|---|---|---|
| Python | pip install urlpipe | PyPI | GitHub | Python 3.9+, sync and async clients, one dependency (httpx) |
| JavaScript | npm install @urlpipe/sdk | npm | GitHub | TypeScript types, no dependencies; Node 18+, Bun, Deno and Cloudflare Workers |
| Ruby | gem install urlpipe | RubyGems | GitHub | Ruby 3.1+, no dependencies |
| Go | go get github.com/URLpipe/urlpipe-go | pkg.go.dev | GitHub | Go 1.21+, standard library only |
Your first call
Each client reads the project API key from URLPIPE_API_KEY (or takes it as an argument) and waits for the result, so a call returns the page:
import urlpipe
client = urlpipe.Client() # reads URLPIPE_API_KEY
page = client.markdown("https://example.com")
print(page.data)import Urlpipe from "@urlpipe/sdk";
const client = new Urlpipe(); // reads URLPIPE_API_KEY
const { data } = await client.markdown("https://example.com");
console.log(data);require "urlpipe"
client = Urlpipe::Client.new # reads ENV["URLPIPE_API_KEY"]
page = client.markdown("https://example.com")
puts page.dataclient, err := urlpipe.NewClient() // reads URLPIPE_API_KEY
if err != nil {
log.Fatal(err)
}
page, err := client.Markdown(context.Background(), "https://example.com", nil)
if err != nil {
log.Fatal(err)
}
fmt.Println(page.Data)What every client does
- Waits for the result. Calls send
sync: trueby default. When a page outlives the 60-second sync window, the API answers504with a token and the client polls GET /result/:token until the result lands, so your code sees one call. Passsync: falsefor a token straight away, andwait(token)to collect it. - Retries without paying twice. Connection errors, 5xx answers,
rate_limitedandconcurrency_limitare retried with backoff, and every retried request carries an Idempotency-Key, so a retry can never run or bill the work twice. - Types every error. Each documented error — invalid key, unconfirmed email, invalid request, failed analysis, out of credits, too many in parallel, rate limited, not found, expired — is its own type, with the API's code, message and fields.
- Reads the metadata. The response headers — cache status and age, processing time, credits spent and left — come back parsed on every response.
- Verifies webhooks. A helper checks a delivery's HMAC signature against the raw body, accepts either secret during a rotation, and refuses stale timestamps.
Every option the API takes can be passed, including ones newer than your client version: each client has an
extra map that is merged into the request body as it is.From an AI agent
Agents don't need a library at all: the hosted MCP server gives Claude, Cursor, VS Code and other clients the same operations as tools, with one token.