How-to6 min read

Free PDF API Without an API Key: What Anonymous Calls Get

PDF123's REST API runs without an API key or account. Merge and Compress with curl, the size limits, the error body and what to do on HTTP 429.

By the PDF123 team · Updated 2026-11-01

Yes. The PDF123 REST API takes requests with no API key and no account: in a test run, a plain curl to the Merge endpoint and then to the Compress endpoint returned HTTP 200 and a PDF, without an X-API-KEY header. What limits a call is its size and, for chunked uploads, how many are open at once, not who sent it: one request body holds up to 100 MiB, and every response carries X-RateLimit-* headers.

Is there a free PDF API that needs no API key?

For anonymous use, yes: the developer page states that calls to the public API need no account and no key. The OpenAPI document names X-API-KEY as its authentication scheme, but the calls below ran without it.

The commands were run against a locally running copy of the server on 2026-10-23, with the origin swapped for https://pdf123.xyz here. The inputs were two one-page PDFs made from two short Markdown files. Merge takes one fileInput part per file, in the order the pages should appear:

curl -X POST https://pdf123.xyz/api/v1/general/merge-pdfs \
  -F [email protected] -F [email protected] \
  -o merged.pdf

The response was HTTP 200 with content-type: application/pdf. qpdf --show-npages merged.pdf printed 2, and pdftotext read the text of a.pdf first, then b.pdf. The download is named after the first input, a.pdf, so rename it before you save it next to the original.

Compress takes one file:

curl -X POST https://pdf123.xyz/api/v1/misc/compress-pdf \
  -F [email protected] \
  -o small.pdf

That was also HTTP 200. The response headers X-Original-Bytes: 28564 and X-Compressed-Bytes: 25113 match the two file sizes on disk, so a script can read what the call did without opening the file. Those numbers describe one tiny test file and say nothing about what Compress will do to yours.

Which limits apply without a key?

The server reports its size limits at GET /api/v1/info/status, which also needs no key. The values it returned, converted to MiB (1 MiB is 1,048,576 bytes):

Field Value What it limits
maxUploadBytes 104,857,600 (100 MiB) One direct request body, multipart framing included
maxChunkedUploadBytes 524,288,000 (500 MiB) One file sent through the chunked upload API
uploadChunkBytes 33,554,432 (32 MiB) The size of each chunk
maxOcrPages 50 Pages that need recognition in one OCR request

The Limits page reads the same endpoint and adds the website's own caps, such as batches. The error an over-size body returns is covered in PDF Upload Rejected? The 100 MiB Request Limit Explained.

Every response, including the ones above, carried three headers: x-ratelimit-limit: 100000, x-ratelimit-remaining: 100000 and x-ratelimit-reset: 0. The numbers did not change across the calls I made. The server writes 100000 when no period cap is configured and always writes 0 for reset, so on that server the headers advertise no quota that counts down. They tell you nothing about the quota of pdf123.xyz at any later date: read them on your own responses instead of hard-coding a number. No Sign-In Needed: How Anonymous Rate Limiting Works says more about what the headers are for.

Where are the endpoints documented?

The OpenAPI 3 document is served at https://pdf123.xyz/v1/openapi.json, and https://pdf123.xyz/swagger-ui opens the same API in a page where you can try each endpoint. Every operation is a POST under /api/v1, grouped by category: Merge is /general/merge-pdfs, Compress is /misc/compress-pdf. The tool pages on the website call the same endpoints.

For copy-and-run examples, Recipes shows common jobs as curl, pdfx and Node. The Developers page covers the SDK, the command line and MCP as well.

What does an error look like, and what should a client do on a 429?

A failed call returns application/problem+json, the format defined in RFC 9457, Problem Details for HTTP APIs. Sending a text file named fake.pdf twice to Merge returned HTTP 400 with this body (reformatted here, keys in the order returned):

{
  "code": "invalid_document",
  "detail": "The file is not a valid PDF or it is damaged.",
  "error": "The file is not a valid PDF or it is damaged.",
  "hint": "Upload a valid, undamaged PDF. Try the Repair tool first.",
  "reason": "invalid_pdf",
  "status": 400,
  "title": "Bad Request",
  "type": "https://pdf123.xyz/developers/errors#invalid_document"
}

code is the coarse class and reason is the specific cause. Error codes lists both and says to branch on reason and fall back to code. error repeats detail for older clients.

The one 429 I could produce on that server came from chunked uploads: with 32 uploads open, the request to start a 33rd was refused. The response was HTTP 429 with reason set to upload_limit_reached, code set to rate_limited, and a retry-after: 60 header, next to the usual x-ratelimit-* headers. The limit of 32 is the server's default and can be set differently on another server. Operation calls such as Merge and Compress never returned 429 in my runs, but a client should still handle it: the developer page lists rate_limited with status 429 as the answer when a quota is used up. RFC 6585 defines the status as meaning too many requests in a given amount of time, and says the server may include Retry-After to say how long to pause.

What a client should do on a 429:

  • Wait for the number of seconds in Retry-After (60 in the response I saw), then send the same request again. Do not retry in a tight loop.
  • If the reason is upload_limit_reached, finish or abandon the uploads you left open. DELETE /api/v1/uploads/{id} aborts one, and an unfinished upload expires after an hour.
  • Do the waiting yourself. The SDK, the pdfx command line and the MCP server do not retry on their own.

When is an API key worth creating?

The developer page gives two reasons: to identify your own traffic, and to call the hosted MCP endpoint at https://pdf123.xyz/mcp, which always requires a key. On the server I ran, a request to /mcp without a key returned 401. You create a key on that page after signing in, and send it in the X-API-KEY header. For the REST API, the SDK and the command line on the public site, no key is required. On a server you host yourself, one key can be set through the SECURITY_CUSTOMGLOBALAPIKEY environment variable.

Questions people ask

Is the PDF123 API really free?

Anonymous calls to the public API need no account and no key, and the examples above ran without either. The limits are the ones in the table above, and the headers on your own responses are the source of truth for any quota.

Do I have to sign in to call it?

No. Signing in is only needed to create a key, which the hosted MCP endpoint requires and the REST API does not.

Can I send a PDF larger than 100 MiB?

Yes, up to 500 MiB per file through the chunked upload API: create an upload, send each 32 MiB chunk, complete it, then pass its id to the operation. The TypeScript SDK and pdfx switch to it automatically. The steps are under "Files over 100 MB" on the Error codes page.

How do I know which limits the server I call has?

Call GET /api/v1/info/status. It reports the request size, the chunked upload size and chunk size, and the OCR page limit of that server, which is where the Limits page gets its numbers.

Open tool
Process in the browser — no watermark, files removed after the job.
Open tool