Extract text from a PDF
Feed a native PDF into this endpoint and get its embedded text back as plain, reusable content — no fonts, no columns, no coordinates to fight, just the words the document already contains. It is built for search indexes, keyword pipelines, and any process that needs the words, not the page.
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.
The specific job this does
Most tools that touch PDFs try to preserve everything — layout, images, formatting — which is exactly wrong when all you want is the text for indexing, comparing, or feeding into a downstream process. This endpoint has one job: read the text layer a PDF already carries and hand it back as a plain string, in reading order, without you writing a parser or fighting a rendering library. It is for the case where the destination is a search index, a database column, or a script, not a human reading the page.
What it expects and what it returns
You POST the PDF to /pdf/to-text and receive a task_id immediately, since extraction runs asynchronously even though it is typically fast. The result — delivered by webhook or a signed link valid for 24 hours — is the document's text content, page by page or as one stream depending on how you request it. This works cleanly on native, text-based PDFs: files exported from a word processor, generated by code, or produced by another step in your own pipeline, where the words are stored as text rather than as pixels.
Why 'native' matters, and where scanned pages fit
PDF has always supported two very different kinds of pages: one where letters are stored as actual text objects with font references, and one where a page is really just an embedded image — the output of a scanner. Text extraction reads the first kind directly, because the words are already there in the file. A scanned page has no such layer; it is a photograph of text, and getting words out of it is a recognition problem, not an extraction one, which is a different task with a different cost profile than this endpoint.
Where this fits in an automated flow
Because it returns a task_id and reports over a webhook, PDF to Text drops into ingestion pipelines the same way any other async step does: a document lands in storage, this endpoint pulls its text, and a downstream job indexes it, classifies it, or checks it for a keyword before routing it further. Run it across a folder of thousands of files and let each completion event advance its own document independently — no polling loop required. Only requests that actually complete are billed.
Cost, access, and retention
Pricing is flat and simple: $0.002 per request, with no per-page surcharge, so extracting text from a hundred documents costs twenty cents regardless of how long any of them are. Using the endpoint requires prepaid balance — without it the call returns a 402, by design, which keeps the extraction queue fast and free of abuse. The PDF you send and the text it produces are kept only through the retention window, then deleted, and never used for training.
What you can do with it
Full-text search indexing
Pull the text out of every PDF in a document library and feed it into a search index, so users can find a file by the words inside it instead of only by its filename.
Compliance and keyword screening
Scan incoming contracts or reports for specific clauses or terms by extracting their text first, then running plain string checks instead of parsing a binary format directly.
Feeding downstream language processing
Extract clean text from PDFs before summarizing, classifying, or translating them, since text-based tools work far better on a plain string than on a page image or a raw PDF stream.
Data migration and archiving
Convert a legacy archive of PDF reports into searchable, storable text records as part of moving that content into a database or content-management system.
FAQ
How do I extract text from a PDF using an API?
POST the PDF to /pdf/to-text and you get a task_id back right away. The extracted text arrives on your webhook or a signed link once the task finishes.
Is the PDF to Text API free to use?
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.
How much does PDF text extraction cost?
It is a flat $0.002 per request with no per-page fee, so the cost is the same whether the PDF has one page or a hundred.
Does it work on scanned PDFs?
It is built for native, text-based PDFs where letters are stored as text objects. A scanned page is really an image, so it has no text layer to extract and requires a different kind of process entirely.
Does it preserve formatting, tables or columns?
No — the output is plain text in reading order, without fonts, layout or column structure, which is exactly what you want for search or downstream text processing.
Can I extract text from a large batch of PDFs at once?
Yes. Each PDF is its own independent task, so you can submit thousands of files and let each webhook confirm completion without polling.
What happens if a PDF cannot be processed?
The task retries automatically up to three times before returning a clear error, and you are never charged for a request that ultimately fails.
How long is the extracted text available, and is it stored afterward?
The signed link is valid for 24 hours. After the retention window, both the source PDF and the extracted text are deleted and never used to train anything.
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/to-text \
-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/to-text", {
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/to-text",
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/to-text", 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/to-text", 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.to_text",
"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. |