Split a PDF by bookmarks
A 400-page manual whose author bookmarked each chapter becomes one file per top-level bookmark, with no page counting by hand. Send each department its own chapter or turn a merged set of contracts back into single files. You pay per document, with no subscription.
This task is not available right now, so it cannot be purchased. Nothing is charged for it.
How it works & APIA 400-page manual or report already knows where its own chapters begin, because its author bookmarked them, yet most people still split such files by counting pages by hand.
The manual split nobody should have to do
Long PDFs — technical manuals, compiled reports, merged chapter drafts, government publications — are usually built with a bookmark outline already in place, added either by the authoring tool or by whoever assembled the final document. That outline is a perfectly structured map of where each section starts and ends, yet splitting the file still often means opening it, scrolling to find each boundary, and exporting page ranges by hand.
How the split is decided
The engine reads the document's existing bookmark outline and uses each top-level bookmark as a section boundary: every entry becomes the start of a new file, which runs until the next top-level bookmark begins or the document ends. The result is a set of files that mirrors the document's own table of contents, with page content, formatting and images preserved exactly as they appeared in the source.
Why bookmarks are the right signal to split on
PDF bookmarks, technically the document outline, have been part of the format since its early versions specifically to let long documents be navigated without scrolling through hundreds of pages — the same feature that shows a clickable table of contents in a PDF reader's sidebar.
Because that outline is written by whoever produced the document and typically maps directly onto chapters, sections or standalone reports bundled into one file, it's a far more reliable split signal than fixed page counts or blank-page detection, which can misfire on documents that don't follow a strict page pattern.
Where it saves real time
It's built for exactly the kind of document that arrives as one large PDF but is consumed section by section: a compiled annual report where each department wants only its own chapter, a merged set of contracts that needs to become individual files again, a training manual whose modules should be distributed separately, or a bound government filing split back into its original component documents. Running this as one step in a pipeline replaces what would otherwise be a manual, error-prone page-counting exercise every time a new large document arrives.
What you can do with it
Distribute a training manual module by module
Split a single bookmarked training manual into one file per module, so each team only receives the section relevant to them instead of the entire document.
Break a compiled annual report into departmental chapters
Turn one large report PDF with bookmarks for each department into individual files, so each team gets exactly its own chapter without the rest of the document.
Recover individual contracts from a merged PDF
Split a bookmarked PDF containing several merged contracts back into separate files, one per contract, undoing an earlier merge step cleanly.
Separate a government filing into its component documents
Split a bound multi-document filing along its bookmark structure to recover the original standalone documents it was assembled from.
FAQ
Does it split on nested sub-bookmarks too?
It uses top-level bookmark entries as the section boundaries, so nested sub-bookmarks stay inside their parent section's file rather than creating additional splits.
Will formatting, images and layout stay intact after splitting?
Yes. Each output file preserves the exact page content, formatting and images from the source document; nothing is re-rendered or altered.
How are the output files named?
Each output file corresponds to one top-level bookmark section from the original document's outline, delivered together as the result of a single task.
Where does each file start and end?
Each top-level bookmark starts a new file, which runs until the next top-level bookmark begins or the document ends. The resulting set of files mirrors the document's own table of contents.
Why split by bookmarks instead of by page count?
Because the bookmarks were written by whoever produced the document and usually match its chapters. Fixed page counts or blank-page detection can misfire on documents that do not follow a strict page pattern.
Related tools
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
One authenticated POST creates the task; the result comes back by webhook or a signed link. This capability is currently available through the API, not as an interactive Web tool.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/pdf/split-by-bookmark \
-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/split-by-bookmark", {
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/split-by-bookmark",
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/split-by-bookmark", 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/split-by-bookmark", 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.split_by_bookmark",
"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. |
Technical notes
This split PDF by bookmarks API reads a document's existing bookmark outline and cuts it into one separate file per top-level entry, turning a table of contents into an actual set of files.
The manual split nobody should have to do
This endpoint exists because that map was already there; it just needed to be read and acted on automatically.
How the split is decided
Call POST /pdf/split-by-bookmark with the source PDF and get a task_id back immediately, since the split runs asynchronously.
Delivery and pricing
The resulting files are delivered by a signed webhook, recommended for automation, or a signed link valid for 24 hours; source and output are deleted after the retention window and never used for training. Pricing is a flat $0.002 per request regardless of how many sections the document splits into, and a task that fails after its retry attempts is never charged. This endpoint is live now and ready for production traffic.
Technical questions
How do I split a PDF by bookmarks using an API?
Send the PDF to POST /pdf/split-by-bookmark, which returns a task_id right away. The set of split files, one per top-level bookmark, arrives by webhook or signed link once processing completes.
Is the split PDF by bookmarks 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.
What happens if my PDF has no bookmarks?
This endpoint splits based on an existing bookmark outline, so a document without any bookmarks has no boundaries to split on; add an outline first or use a page-range-based split instead.
Can I split many bookmarked PDFs in bulk?
Yes. Each request is an independent asynchronous task, so you can submit a large batch of documents in parallel and collect each set of split files by webhook.
Is this endpoint live right now?
Yes, it is live and accepting production traffic today.