Read PDF metadata
Every PDF carries a hidden information dictionary: the title, the author, the tool that produced it, and the timestamps for when it was created and last touched. This PDF metadata API pulls those fields out of any document you send it and returns them as clean, structured JSON, so you never have to parse the file yourself.
Run it online
Run this on our servers with your account. Free tools run in your browser; this one bills your KIT balance per the price above.
What it reads, and why that matters
Send a PDF and get back the fields most people never see: Title, Author, Subject, Keywords, Creator (the authoring application), Producer (the library that wrote the file), plus the CreationDate and ModDate timestamps. These live in the document's information dictionary and, on modern files, in an embedded XMP packet. For a document management system, a legal archive, or a publishing pipeline, that metadata is the difference between a searchable, well-labeled library and a folder of anonymous blobs. Reading it reliably across the messy variety of real-world PDFs is exactly the tedious work this endpoint takes off your plate.
How the request works
You call POST /pdf/metadata-read with a reference to your document and the request returns immediately with a task_id. Because a large or awkwardly encoded PDF should never block your request thread, the work runs asynchronously on our global edge. When it finishes, the structured result is delivered to you — no polling loops, no held-open connections. If a task fails, we retry three times with backoff before returning a clear, actionable error, and a failed task is never billed.
A note on the format itself
The PDF format has carried an information dictionary since its earliest public specifications in the 1990s, and Adobe later layered XMP — an XML-based metadata standard — on top of it so that richer, standardized fields could travel with the file. The catch is that the two can disagree, dates use PDF's own quirky string format, and many producers leave fields blank or stamped with the name of whatever tool exported them. We normalize what we can, expose dates in a predictable shape, and hand you both sources so nothing meaningful is silently dropped.
Delivery, retention, and privacy
Results arrive by a signed webhook, which we recommend for automation, or through a signed link that stays valid for 24 hours. Your document and its extracted metadata are held only for the retention window and then deleted; nothing you send is ever used to train any model. This keeps the surface small and predictable, which is part of why the service stays fast.
Where it fits in automation
Because each call is a small, cheap, self-contained unit, this endpoint slots naturally into an ingestion step. Drop it at the front of an intake pipeline to auto-tag every incoming file by author and creation date, to flag documents whose Producer reveals an unexpected origin, or to reconcile a claimed date against the embedded one — all before a human ever opens the file.
What you can do with it
Auto-tag a document archive
As files land in a legal or records archive, read each PDF's author, title, and creation date to populate catalog fields automatically, turning an unlabeled dump into a searchable library without manual data entry.
Verify provenance in e-discovery
Compare the embedded CreationDate and ModDate against a document's claimed timeline, and inspect the Producer field to see which tool actually generated a file — useful when the origin of an exhibit is in question.
Quality-gate a publishing pipeline
Before a PDF goes to print or to a distributor, confirm that Title and Author are set correctly and reject files where the metadata is blank or still carries a placeholder from the export tool.
Deduplicate and route incoming mail
Use the Producer and creation timestamp to distinguish a freshly scanned invoice from a re-exported copy, then route each document to the right workflow based on what actually produced it.
FAQ
How do I read metadata from a PDF with an API?
Send your document to POST /pdf/metadata-read and you receive a task_id right away. The extracted title, author, dates, and producer are then delivered to your signed webhook or through a signed link, as structured JSON.
Is the PDF metadata API free?
There's no free tier — free tiers get abused and slow everyone down. Access runs on a prepaid ForHosting KIT balance: top up from $10.00 (it never expires) and each request is charged at its published price, so a call with no balance returns HTTP 402. No subscription, no tokens, no invented credits, and a failed task is never charged.
Which metadata fields does it return?
Title, Author, Subject, Keywords, Creator, and Producer from the document information dictionary, along with the CreationDate and ModDate timestamps. When a file carries an embedded XMP packet, those standardized fields are read as well.
Can it process PDFs in bulk?
Yes. Because every call is an independent asynchronous task returning its own task_id, you can fan out thousands of documents in parallel and collect each result by webhook as it completes, with no shared queue to bottleneck you.
What happens if a PDF has no metadata?
Many files leave fields blank or unset. The response simply returns those fields as empty rather than guessing, so you can tell the difference between a missing value and an actual one — and a valid document with sparse metadata is not treated as a failure.
How are the creation and modification dates formatted?
PDF stores dates in its own string format, which we parse and expose in a predictable, machine-readable shape so you do not have to decode the raw D: prefix and timezone offsets yourself.
Does reading metadata change or extract the document's content?
No. This capability only reads the information dictionary and XMP packet; it does not alter your file, and it does not extract page text or images. Your document is deleted after the retention window.
What happens if the file is corrupt or not a real PDF?
The task is retried three times with backoff, and if it still cannot be read you receive a clear error explaining why. A failed task is never billed.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, and soon from our app, email and Telegram.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/pdf/metadata-read \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"pdf":"https://ejemplo.com/documento.pdf"}'const res = await fetch("https://api.kit.forhosting.com/pdf/metadata-read", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"pdf": "https://ejemplo.com/documento.pdf"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/pdf/metadata-read",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"pdf": "https://ejemplo.com/documento.pdf"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/pdf/metadata-read", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"pdf":"https://ejemplo.com/documento.pdf"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"pdf":"https://ejemplo.com/documento.pdf"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/pdf/metadata-read", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"pdf": "https://ejemplo.com/documento.pdf"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "pdf.metadata_read",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_mb | 25 |
max_pages | 200 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
413 | input_too_large | The file exceeds the size limit. |