PDFBEAR API and MCP server for developers
Compress, convert, merge, split, protect, unlock and OCR PDFs from your own code with a simple REST API, or let an AI assistant do it through our remote MCP server. The same engine that runs pdfbear.com, with a free tier of 100 jobs a month.
Quick start
Every conversion is an asynchronous job: you start it, poll its status, then download the result. Base URL: https://pdfbear.com/api/v1.
- Create a free account, confirm your email, then open Account → Developers / API and create a key.
- Start a job:
curl -X POST https://pdfbear.com/api/v1/jobs \
-H "Authorization: Bearer $PDFBEAR_API_KEY" \
-F tool=compress-pdf \
-F file=@report.pdf \
-F 'options={"compression_level":"recommended"}'
# 202 Accepted
{"job_id": "job_3f2c9a0e8b7d4c1e9f6a5b4c3d2e1f00", "status": "queued",
"tool": "compress-pdf", "status_url": "https://pdfbear.com/api/v1/jobs/job_3f2c..."}
- Poll until
statusiscompleted, then download:
curl https://pdfbear.com/api/v1/jobs/job_3f2c9a0e8b7d4c1e9f6a5b4c3d2e1f00 \
-H "Authorization: Bearer $PDFBEAR_API_KEY"
curl -L -o report-small.pdf \
https://pdfbear.com/api/v1/jobs/job_3f2c9a0e8b7d4c1e9f6a5b4c3d2e1f00/download \
-H "Authorization: Bearer $PDFBEAR_API_KEY"
Most jobs finish in a few seconds. Poll every 1-2 seconds; status requests count toward the rate limit but not toward your monthly job quota.
Authentication
Send your key in the Authorization header on every request: Authorization: Bearer pdfb_live_.... Keys are 42 characters long and start with pdfb_live_. We store only a SHA-256 fingerprint, so a key is shown once when you create it; if you lose it, revoke it and create a new one. Keys never expire, and revoking one takes effect immediately.
Keep keys on your server. Anyone who has a key can run jobs on your quota.
CORS: /api/v1 and /mcp send Access-Control-Allow-Origin: *, so browsers are allowed to call them (no cookies are used; the key is the only credential). Only do that from a private tool or an app where the user enters their own key: a key embedded in a public web page can be copied by anyone. For public sites, call the API from your server.
Plans, quotas and limits
Free tier at a glance: 100 jobs per month, 60 requests per minute per key, 50 MB per file, no credit card.
| Free account | Premium | |
|---|---|---|
| API jobs per calendar month (UTC) | 100 | 2,000 |
| Requests per minute, per key | 60 | 60 |
| Max size per input file | 50 MB | 90 MB |
| Max pages per job | 30 | 200 |
| AI tools (OCR, summarize, AI Word engine) | No | Yes, within the fair-use allowance |
| PDF output | Small "PDFBEAR.COM - Free Ver." badge in the lower-right corner of each page | Clean, no badge |
| CORS (browser calls) | Allowed (Access-Control-Allow-Origin: *) | Allowed |
| Result link lifetime | 30 days | While your subscription is active |
protect-pdf and cleaned PDFs from remove-watermark-pdf are also exempt. Premium output is always clean. Each job's status says whether its result carries the badge (free_badge).Every created job counts toward the monthly quota, including jobs that later fail. Requests that are rejected before a job is created (bad key, invalid options, a file that is too large) do not count. GET /api/v1/me shows what you have left. Total upload size per request is capped at 95 MB; for bigger merges, pass file_urls instead.
Endpoints
GET/api/v1/tools
Lists every tool the API offers with its accepted input types, output format, option schema and whether it needs Premium. No key needed.
POST/api/v1/jobs
Starts a job and returns 202 Accepted with job_id and status_url. Send either multipart/form-data or JSON:
| Field | Description |
|---|---|
tool | Required. A tool_id from the table below, e.g. compress-pdf. |
file / files | Multipart upload. merge-pdf takes 2 or more files; compare-pdf takes exactly 2. |
file_url / file_urls | A public http(s) URL we download the input from (JSON or form). Private and internal addresses are refused. |
content_base64 + filename | JSON only: the file inline, base64-encoded. files: [{filename, content_base64}] for merges. |
url | html-to-pdf renders a web page and rss-to-pdf fetches a feed. For file tools it is treated like file_url. |
options | Tool options: a JSON object (in multipart, a JSON string). Unknown options are rejected. |
curl -X POST https://pdfbear.com/api/v1/jobs \
-H "Authorization: Bearer $PDFBEAR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"tool": "html-to-pdf", "url": "https://example.com",
"options": {"page_size": "A4", "remove_popups": true}}'
curl -X POST https://pdfbear.com/api/v1/jobs \
-H "Authorization: Bearer $PDFBEAR_API_KEY" \
-F tool=merge-pdf -F files=@part1.pdf -F files=@part2.pdf
GET/api/v1/jobs/{job_id}
Returns status: queued, processing, completed, needs_action or failed. needs_action means the file or selected method must change; failed means PDFBEAR had a system problem. Both include error.message. A completed job includes:
{
"job_id": "job_3f2c9a0e8b7d4c1e9f6a5b4c3d2e1f00",
"tool": "compress-pdf",
"status": "completed",
"created_at": "2026-09-26T10:15:02Z",
"finished_at": "2026-09-26T10:15:05Z",
"input": {"filename": "report.pdf", "size": 4812331},
"download_url": "https://pdfbear.com/api/v1/jobs/job_3f2c.../download",
"public_url": "https://pdfbear.com/downloads/converted/converted_9b1e....pdf",
"filename": "report.pdf",
"size": 1022456,
"content_type": "application/pdf",
"expires_at": "2026-10-26T10:15:02Z",
"expired": false,
"free_badge": true
}
download_url needs your key. public_url is the same unguessable, expiring link the website gives you, and it opens in any browser without a key, so treat it like a password-free share link.
GET/api/v1/jobs/{job_id}/download
Streams the result file with a proper Content-Disposition filename. Returns 409 while the job is still running and 410 once the result has expired.
GET/api/v1/me
Your plan, this month's job quota (limit, used, remaining, resets_at) and your limits.
Tools and options
| tool_id | What it does | Input | Output | Options | Plan |
|---|---|---|---|---|---|
compress-pdf |
Reduce PDF file size (lossless or with image downsampling). | compression_level (less | recommended | extreme) |
Free | ||
merge-pdf |
Combine 2 or more PDFs into one, in the order given. | 2+ .pdf | - | Free | |
split-pdf |
Split a PDF into several PDFs (returned as a ZIP). | ZIP | mode (all | ranges | fixed | size | smart-blank | smart-headings)ranges (string)merge_ranges (boolean)every_n_pages (integer)max_size_mb (number)omit_separators (boolean) |
Free | |
pdf-to-word |
Convert a PDF to an editable Word document (.docx). | DOCX | engine (standard | ai) |
Free | |
word-to-pdf |
Convert a Word document (DOC/DOCX/ODT/RTF) to PDF. | .doc, .docx, .odt, .rtf | - | Free | |
pdf-converter |
Detect a supported document or image format and convert it to PDF. | .doc, .docx, .odt, .rtf, .txt, .html, .htm, .xls, .xlsx, .ppt, .pptx, .jpg, .jpeg, .png, .tif, .tiff, .webp, .bmp, .gif, .heic, .heif, .ods, .odp, .csv, .hwp, .pages, .epub, .zip | - | Free | |
pdf-to-jpg |
Render every PDF page as a JPG image (returned as a ZIP). | ZIP | - | Free | |
jpg-to-pdf |
Convert a JPG or PNG image to a PDF. | .jpg, .jpeg, .png | - | Free | |
rotate-pdf |
Rotate all pages, or selected pages, of a PDF. | angle (90 | 180 | 270)pages (string) |
Free | ||
protect-pdf |
Encrypt a PDF with an open password. | password (string), required |
Free | ||
unlock-pdf |
Remove the password/encryption from a PDF you are allowed to open. | password (string)guess_password (boolean) |
Free | ||
remove-watermark-pdf |
Remove text/image/annotation watermarks from a PDF (automatic structural mode). | watermark_text (string)target_color (string) |
Free | ||
pdf-to-pdfa |
Convert a PDF to PDF/A-2b for long-term archiving. | - | Free | ||
html-to-pdf |
Render a public web page (http/https URL) to PDF, JavaScript included. | web page URL | page_size (A3 | A4 | A5 | Letter)orientation (portrait | landscape)margin (none | small | big)screen_width (integer)one_long_page (boolean)block_ads (boolean)remove_popups (boolean) |
Free | |
ocr-pdf |
Make a scanned PDF searchable with AI OCR. | - | Premium | ||
summarize-pdf |
Create an AI summary of a PDF and return it as text. | TXT | length (short | medium | long)tone (neutral | formal | casual | academic | simple) |
Premium | |
excel-to-pdf |
Convert an Excel spreadsheet (XLS/XLSX/ODS) to PDF. | .xls, .xlsx, .ods | - | Free | |
ppt-to-pdf |
Convert a PowerPoint presentation (PPT/PPTX/ODP) to PDF. | .ppt, .pptx, .odp | - | Free | |
rss-to-pdf |
Turn a public RSS or Atom feed into a readable PDF. | web page URL | max_items (integer)content_mode (full | summary)include_images (boolean)page_size (A3 | A4 | A5 | Letter)margin (none | small | big) |
Free | |
pdf-to-excel |
Extract PDF tables and content into an editable Excel workbook (.xlsx). | XLSX | - | Free | |
pdf-to-ppt |
Convert PDF pages into an editable PowerPoint presentation (.pptx). | PPTX | - | Free | |
pdf-to-png |
Render every PDF page as a PNG image (returned as a ZIP). | ZIP | - | Free | |
delete-pages-from-pdf |
Remove selected pages from a PDF and return a new PDF. | pages (string), required |
Free | ||
resize-pdf |
Resize PDF pages to a paper preset or scale percentage. | mode (preset | scale)preset (a3 | a4 | a5 | letter | legal)scale (number) |
Free | ||
repair-pdf |
Repair a damaged or malformed PDF and recover readable content. | - | Free | ||
add-page-numbers-to-pdf |
Add visible page numbers to a PDF. | position (bottom_center | top_center | bottom_right | top_right | bottom_left | top_left)start_page (integer) |
Free | ||
add-watermark-pdf |
Add a text watermark to a PDF. | watermark_text (string), requiredfont_size (integer)font (helvetica | arial | times | courier)bold (boolean)italic (boolean)color (string)opacity (number)rotation (integer)position (center | top_left | top_center | top_right | middle_left | middle_right | bottom_left | bottom_center | bottom_right)mosaic (boolean)underline (boolean)page_from (integer)page_to (integer)layer (over | below) |
Free | ||
scan-to-pdf |
Turn a photo or document scan into a searchable PDF with OCR. | .jpg, .jpeg, .png | - | Premium | |
crop-pdf |
Automatically trim PDF margins or crop every page to a fractional box. | crop_box (object) |
Free | ||
extract-pages-from-pdf |
Extract selected pages or ranges into a new PDF. | pages (string), required |
Free | ||
organize-pdf |
Reorder, rotate, and remove PDF pages in one operation. | page_order (array)deletions (array)rotations (object) |
Free | ||
compare-pdf |
Compare exactly two PDFs and create a color-coded text-difference report. | 2+ .pdf | - | Free | |
pdf-forms |
Create interactive fields in a PDF or fill its existing form fields. | field_values (object)created_fields (array) |
Free | ||
translate-pdf |
Translate PDF text into another language while preserving the layout where possible. | target_lang (string), required |
Premium | ||
redact-pdf |
Permanently redact matching text or specified page areas from a PDF. | redact_terms (string)redact_areas (array) |
Free | ||
png-to-pdf |
Convert a PNG image to PDF. | .png | - | Free | |
heic-to-pdf |
Convert an iPhone HEIC or HEIF image to PDF. | .heic, .heif | - | Free | |
tiff-to-pdf |
Convert a TIFF image or scan to PDF. | .tiff, .tif | - | Free | |
webp-to-pdf |
Convert a WebP image to PDF. | .webp | - | Free | |
bmp-to-pdf |
Convert a BMP bitmap image to PDF. | .bmp | - | Free | |
txt-to-pdf |
Convert a plain-text TXT file to PDF. | .txt | - | Free | |
rtf-to-pdf |
Convert a Rich Text Format document to PDF. | .rtf | - | Free | |
odt-to-pdf |
Convert an OpenDocument Text document to PDF. | .odt | - | Free | |
pdf-to-text |
Extract selectable PDF text into a plain TXT file. | TXT | - | Free | |
extract-images-from-pdf |
Extract embedded raster images from a PDF (returned as a ZIP). | ZIP | - | Free | |
flatten-pdf |
Flatten form fields, annotations, and layers into permanent PDF page content. | - | Free | ||
pdf-question-generator |
Generate study or quiz questions with answers from a PDF. | - | Premium | ||
pdf-accessibility-checker |
Check a PDF for common accessibility issues and return a text report. | TXT | - | Free | |
pdfa-checker |
Pre-check a PDF for common PDF/A conformance issues and return a text report. | TXT | - | Free | |
pdf-to-markdown |
Convert selectable PDF text and structure into Markdown. | MD | - | Free | |
ods-to-pdf |
Convert an ODS spreadsheet to PDF. | .ods | - | Free | |
odp-to-pdf |
Convert an ODP presentation to PDF. | .odp | - | Free | |
csv-to-pdf |
Convert a CSV table to PDF. | .csv | - | Free | |
hwp-to-pdf |
Convert a Hangul HWP document to PDF. | .hwp | - | Free | |
pages-to-pdf |
Convert an Apple Pages document with an embedded PDF preview to PDF. | .pages | - | Free | |
epub-to-pdf |
Convert EPUB chapters into a readable PDF. | .epub | - | Free | |
zip-to-pdf |
Convert supported files in a ZIP archive and merge them into one PDF. | .zip | - | Free | |
svg-to-pdf |
Convert an SVG vector image to PDF. | .svg | - | Free | |
edit-pdf |
Apply structured text, annotation, shape, image, or redaction edits to a PDF. | edits (object)text_edits (array)coords (points) |
Free | ||
pdf-annotator |
Add structured annotations, text, shapes, or images to a PDF. | edits (object)text_edits (array)coords (points) |
Free | ||
esign-pdf |
Place user-provided signature edit objects on a PDF. | edits (object), requiredcoords (points) |
Free | ||
presentation-maker |
Create a researched, designed PDF slide deck from a topic or brief. | topic (string), requirednum_slides (integer)audience (string)tone (string)theme (auto | azure | midnight | emerald | plum | sunset | slate) |
Free |
Notes: pdf-to-word with a scanned (image-only) PDF needs AI OCR, which is Premium. unlock-pdf is for files you are allowed to open; guess_password (trying common passwords) is Premium. remove-watermark-pdf runs the automatic mode; on a free account the output still carries the PDFBEAR free badge. The full machine-readable list is at /api/v1/tools.
Python example
import json, os, time, requests
API = "https://pdfbear.com/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['PDFBEAR_API_KEY']}"}
def run(tool, path, **options):
with open(path, "rb") as fh:
r = requests.post(f"{API}/jobs", headers=HEADERS,
data={"tool": tool, "options": json.dumps(options)},
files={"file": fh})
r.raise_for_status()
job = r.json()
while job["status"] in ("queued", "processing"):
time.sleep(1.5)
job = requests.get(job["status_url"], headers=HEADERS).json()
if job["status"] == "failed":
raise RuntimeError(job["error"]["message"])
out = requests.get(job["download_url"], headers=HEADERS)
out.raise_for_status()
with open(job["filename"], "wb") as fh:
fh.write(out.content)
return job["filename"]
print(run("compress-pdf", "report.pdf", compression_level="extreme"))
JavaScript example
Node.js 20 or newer (built-in fetch, FormData and fs.openAsBlob):
import { openAsBlob } from "node:fs";
import { writeFile } from "node:fs/promises";
const API = "https://pdfbear.com/api/v1";
const headers = { Authorization: `Bearer ${process.env.PDFBEAR_API_KEY}` };
async function run(tool, path, options = {}) {
const form = new FormData();
form.append("tool", tool);
form.append("options", JSON.stringify(options));
form.append("file", await openAsBlob(path), path.split("/").pop());
let res = await fetch(`${API}/jobs`, { method: "POST", headers, body: form });
let job = await res.json();
if (!res.ok) throw new Error(job.error.message);
while (job.status === "queued" || job.status === "processing") {
await new Promise((r) => setTimeout(r, 1500));
job = await (await fetch(job.status_url, { headers })).json();
}
if (job.status === "failed") throw new Error(job.error.message);
const file = await fetch(job.download_url, { headers });
await writeFile(job.filename, Buffer.from(await file.arrayBuffer()));
return job.filename;
}
console.log(await run("pdf-to-word", "contract.pdf"));
Errors
Errors always look like {"error": {"code": "quota_exceeded", "message": "..."}}. Branch on code; the message is written for humans.
| HTTP | code | Meaning |
|---|---|---|
| 400 | bad_request | The body is not multipart or a JSON object. |
| 401 | missing_api_key, invalid_api_key, api_key_revoked | Send a valid key as Authorization: Bearer .... |
| 403 | email_unverified | Confirm the email address on your account. |
| 403 | premium_required | The tool or option needs Premium (AI tools, scanned PDFs, password recovery). |
| 404 | job_not_found, not_found | No such job on your account, or no such endpoint. |
| 409 | job_not_ready, job_failed | Download requested before the job completed, or after it failed. |
| 410 | result_expired | The result is past its expiry date. Run the job again. |
| 413 | file_too_large, too_many_pages, too_many_files | The input is over a size, page or file-count limit. |
| 422 | validation_error, unknown_option, missing_input, unsupported_tool, unsupported_file_type, empty_file, unsafe_url, url_fetch_failed | The request is well-formed but can't be processed as sent. |
| 429 | rate_limited | Over 60 requests a minute on this key. Wait for Retry-After seconds. |
| 429 | quota_exceeded | This month's job quota is used up. Retry-After points at the reset. |
| 429 | ai_allowance_exhausted | The Premium fair-use AI allowance for this billing period is used up. |
| 500 | internal_error | Our fault. Retry, and contact support if it keeps happening. |
A job that is accepted but then fails (for example a corrupted PDF) is not an HTTP error: the job's status is failed and error.message explains what went wrong.
MCP server
PDFBEAR runs a remote Model Context Protocol server, so AI assistants such as ChatGPT, Claude, Cursor and VS Code agents can use PDFBEAR tools directly. Endpoint: https://mcp.pdfbear.com (Streamable HTTP transport, stateless). Python handles the MCP and OAuth protocols; the dedicated hostname is an Nginx reverse proxy. It uses the same account, quota and plan rules as the REST API.
Each API workflow is an MCP tool (compress_pdf, merge_pdf, pdf_to_word, html_to_pdf, ...) plus get_job. ChatGPT can pass conversation attachments through native file parameters. Other MCP clients can give a tool a file_url, or a small file (up to 10 MB) as content_base64 + filename. The call waits for the job and returns a download link; if the job needs longer, it returns the job_id to check with get_job.
For a narrowly scoped integration, use the machine-only endpoint https://mcp.pdfbear.com/<tool-id> (for example, /compress-pdf). A scoped endpoint exposes only that workflow and the support tools; the root endpoint exposes the complete catalog. Scoped endpoints accept MCP POST requests but do not publish separate web pages.
Claude Code
claude mcp add --transport http pdfbear https://mcp.pdfbear.com \
--header "Authorization: Bearer pdfb_live_..."
Claude Desktop
Add this to claude_desktop_config.json (Settings → Developer → Edit Config). It uses the mcp-remote bridge, which needs Node.js:
{
"mcpServers": {
"pdfbear": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://mcp.pdfbear.com",
"--header", "Authorization:${PDFBEAR_AUTH}"],
"env": { "PDFBEAR_AUTH": "Bearer pdfb_live_..." }
}
}
}
Cursor, VS Code and other MCP clients
Any client that supports remote HTTP servers with custom headers works. Cursor (~/.cursor/mcp.json):
{
"mcpServers": {
"pdfbear": {
"url": "https://mcp.pdfbear.com",
"headers": { "Authorization": "Bearer pdfb_live_..." }
}
}
}
VS Code (.vscode/mcp.json):
{
"servers": {
"pdfbear": {
"type": "http",
"url": "https://mcp.pdfbear.com",
"headers": { "Authorization": "Bearer pdfb_live_..." }
}
}
}
For a raw client: POST JSON-RPC 2.0 messages to /mcp with Content-Type: application/json. The server supports protocol versions 2025-06-18, 2025-03-26 and 2024-11-05 and answers every request with a single JSON response (there is no server-sent event stream). A browser GET opens the MCP overview and setup page. initialize, ping and tools/list work without a key so you can inspect the tools; tools/call needs one.
curl https://mcp.pdfbear.com -H "Content-Type: application/json" \
-H "Authorization: Bearer $PDFBEAR_API_KEY" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"compress_pdf",
"arguments":{"file_url":"https://example.com/report.pdf","compression_level":"extreme"}}}'
Changelog
- v1.1.0 (2026-10-03): expanded to 51 callable workflows, including Compare PDF and Presentation Maker; added native ChatGPT file parameters and MCP output schemas.
- v1.0.0 (2026-09-26): first public release. REST API with 15 tools, API keys, monthly quotas, OpenAPI 3.1 spec, and the remote MCP server.
Questions or a tool you'd like to see in the API? Email support@pdfbear.com.