Endpoint reference
POST /api/metadata
Read the basics of a PDF without opening it yourself: page count, page sizes, the Info fields, encryption and whether it has a form. Returns application/json.
Request
Method: POST. URL: https://pdfops.dev/api/metadata. Body: multipart/form-data.
| Field | Type | Required | Description |
|---|---|---|---|
pdf | File (PDF binary) | Yes | Exactly one PDF, up to 4 MB and 2,000 pages. The whole request must stay under 4.5 MB, Vercel's platform request limit. |
password | String | No | Opens a PDF that needs a user password. Not needed for owner-locked files with an empty user password. |
The optional X-API-Key header works as on /api/merge: no header is anonymous, 100 requests per IP per month; a valid key uses your tier's quota; an invalid or revoked key returns 401 invalid_api_key. A successful (2xx) call counts 1 request. Check consumption with GET /api/usage.
Response
On success: 200 OK, Content-Type: application/json:
{
"page_count": 2,
"pages": [
{ "width": 612, "height": 792, "rotation": 0 },
{ "width": 792, "height": 612, "rotation": 90 }
],
"title": "Q3 report",
"author": null,
"subject": null,
"keywords": null,
"creator": "Word",
"producer": "pdfops.dev",
"creation_date": "2026-10-01T09:30:00.000Z",
"modification_date": null,
"encrypted": false,
"has_form": true,
"form_field_count": 12,
"form_field_count_capped": false
}
| Field | Type | Meaning |
|---|---|---|
page_count | number | Pages in the PDF. |
pages | array | One entry per page, up to 2,000. width and height are the media box in points; rotation is the page's rotation in degrees. |
title, author, subject, keywords, creator, producer | string or null | The Info fields. null when absent. |
creation_date, modification_date | string or null | ISO 8601 dates. null when absent. |
encrypted | boolean | true when the PDF had to be decrypted to read it, including owner-locked files with an empty user password. |
has_form | boolean | true when form_field_count is above 0. |
form_field_count | number | AcroForm fields found, counted once each however often a form lists them, and never more than 2,000. Use /api/inspect for the names and types. |
form_field_count_capped | boolean | true when the count stopped at the 2,000-field cap or the form is too large to walk fully, so the real number may be higher. |
On any failure: 4xx or 500, Content-Type: application/json, body is { "error": "<code>", "details": "<explanation>" }.
Error codes
| Error code | Status | Trigger |
|---|---|---|
invalid_multipart | 400 | Request body could not be parsed as multipart/form-data. |
missing_pdf | 400 | The request does not have exactly one pdf file field. |
pdf_too_large | 400 | The pdf file is over 4 MB. |
invalid_pdf | 400 | The PDF could not be parsed (corrupt, or not a PDF). |
encrypted_pdf | 400 | The PDF needs a password we were not given. Owner-locked files with an empty user password (most government blanks) open on their own; for a real user password send it as the password form field. |
decompressed_too_large | 400 | Object streams inside the PDF decompress to over 32 MB. |
too_many_pages | 400 | The PDF has over 2,000 pages. |
request_too_large | 413 | The whole request body is over 4.5 MB (Vercel's platform request limit). Rejected before anything is parsed. |
invalid_api_key | 401 | An X-API-Key header was sent but the key is unknown or revoked. No fallback to the anonymous IP cap. Get a fresh key at /pricing. |
rate_limited (anonymous) | 429 | No X-API-Key header and the per-IP limit (100/month) is exhausted. Retry-After gives seconds until next calendar month. |
rate_limited (keyed) | 429 | Your key's tier quota (Free 250 / Indie 4,000 / Pro 25,000 per month) is exhausted. Retry-After gives seconds until next calendar month. |
Example
curl -X POST https://pdfops.dev/api/metadata \
-F "pdf=@report.pdf" \
-H "X-API-Key: pdfops_live_..." # optional, raises your quota to your tier
Keyless calls work: 100 requests per IP per month with no key.
Using this for real? A free API key raises the keyless 100 calls per IP to 250 requests a month, with no card.
Code examples
Have an API key? Add an X-API-Key header to any request. It is optional, and it raises your quota from 100/IP/month to your tier's.
JavaScript (Node.js 22+) — built-in fetch + FormData
import { readFile } from 'node:fs/promises';
const fd = new FormData();
fd.append('pdf', new Blob([await readFile('report.pdf')], { type: 'application/pdf' }), 'report.pdf');
const res = await fetch('https://pdfops.dev/api/metadata', {
method: 'POST',
headers: { 'X-API-Key': process.env.PDFOPS_API_KEY }, // optional
body: fd,
});
if (!res.ok) {
const err = await res.json();
throw new Error(`PDFops metadata failed: ${err.error}: ${err.details}`);
}
const info = await res.json();
console.log(info.page_count, info.has_form);
Behavioral notes
- The media box is reported as stored. A page with
rotation90 shows its width and height unrotated. - Dates are ISO 8601 strings in UTC, or
null. An Info entry that is not a string, such as a number where the title belongs, is reported asnull. - Encrypted files keep their Info fields. Title, author and dates are read after decryption, including for files that store them in a cross-reference stream.
- A page with no readable media box is reported as 612 by 792, the US Letter size viewers assume.
- Read-only. The PDF is not changed or stored.
- Limits: 4 MB per PDF, 2,000 pages, 4.5 MB per request (Vercel's platform limit).
FAQ
How is this different from /api/inspect?
Metadata describes the document: pages, sizes, Info fields, encryption. Inspect describes the form: every field name, type and option. Metadata only counts the fields.
What does encrypted mean for an owner-locked PDF?
It is true. The PDF had to be decrypted to read it, even when no password was needed.
Related: Set title and author · List form fields · Remove restrictions.
Get a free API key. Keyless calls get 100 requests per IP per month; a free key raises that to 250, with no card. Enter your email and the key arrives in your inbox.