CocoaPDF
Turn structured PDFs into accurate, editable documents—without OCR or AI.
CocoaPDF recovers the text, layout, tables, links, notes, forms, and images already present inside a PDF, then rebuilds them as readable Markdown, structured HTML, and detailed JSON.
How it works Capabilities Installation Usage Python API Diagnostics
CocoaPDF converts digitally born, structured text-layer PDFs into semantic Markdown, loss-aware HTML, and provenance-rich JSON. It parses PDF bytes directly with Python's standard library, reconciles geometry with Tagged-PDF structure, and carries available source-page, region, glyph, MCID, and PDF-object references alongside confidence, evidence, and warnings.
It does not use OCR, AI, or runtime PDF frameworks. Raster images remain images, with their PDF placement, dimensions, alignment, links, captions, and alternative text preserved whenever available.
At a glance
|
01 RECOVER Recover document structure Reading order, paragraphs, headings, lists, tables, figures, notes, forms, and links from PDF-native evidence. |
02 PRESERVE Preserve available evidence Retain available source pages, regions, glyph and MCID references, PDF objects, confidence, evidence, and warnings. |
03 EXPORT Export faithfully Drive Markdown, independent semantic HTML, JSON, reports, and extracted assets from one reconciled document graph. |
Best fit: digitally born reports, manuals, papers, office exports, accessible PDFs, forms, and multi-column documents with selectable text.
Unlike positional text extraction, CocoaPDF reconciles PDF tags with page geometry and falls back conservatively when evidence is ambiguous.
[!IMPORTANT] CocoaPDF does not transcribe text that exists only in raster pixels. It preserves raster content as images, including placement, dimensions, links, captions, and alternative text when encoded by the PDF.
Capability demo
Browse this revision's committed inputs and exact outputs.
On main, open the rendered, side-by-side capability demo.
Same-repository pull requests receive a commit-pinned rendered-demo link in
their description, so reviewing a child branch never silently opens main.
For security, fork pull requests expose the generated review artifact but not
a one-click third-party rendering of contributor-controlled HTML.
The three complex source PDFs, fixture prose, and assets are first-party project material under the bundled MIT license; no downloaded content, OCR, AI, or ML is used. They remain separate because Tagged-PDF structure trees, AcroForm fields, and outlines are document-catalog semantics: concatenating their pages would change the evidence being tested rather than merely combine examples.
The committed examples/ tree is distinct from temporary pull-request review
artifacts. CI regenerates it from the same case definitions and fails if any
checked-in source or output becomes stale.
Benchmark results
CocoaPDF 0.1.0 at commit 59a544a
measured on all 200 documents of the DP-Bench corpus using the unmodified
OpenDataLoader-Bench evaluator at 7af1d8f4,
run twice on 2026-08-02.
| Metric | Mean | Eligible documents |
|---|---|---|
| Overall document-macro score | 0.9020490607 |
200 |
| NID (reading order) | 0.9086028983 |
200 |
| NID-S (tables removed) | 0.8897361669 |
200 |
| TEDS (table structure) | 0.9251323351 |
42 |
| TEDS-S (structure only) | 0.9300636650 |
42 |
| MHS (heading structure) | 0.8791989022 |
107 |
| MHS-S (structure only) | 0.9415827438 |
107 |
200 evaluated, 200 prediction files, 0 missing, 0 empty, and 0 conversion
failures. TEDS is scored only on the 42 documents whose ground truth contains
a table, and MHS only on the 107 that contain a heading; overall_mean is the
mean of each document's available metrics, not the mean of the three aggregates.
Overall, NID, TEDS, and MHS clear the enforced 0.80 floors, and the
document-macro score clears 0.90. Two full runs
produced byte-identical Markdown for all 200 documents and identical aggregate
and per-document scores. The live speed badge is recomputed by trusted CI as
total timed conversion seconds divided by the audited 200-page denominator
bound to the hash-verified corpus; it is one page-weighted s/page observation,
not a per-file range.
See
validation/benchmarks/opendataloader_bench/RESULTS.md
for exact deltas, determinism evidence, and remaining no-OCR limitations.
Evaluation artifacts — result.json, evaluation.json, evaluation.csv,
summary.json, provenance.json, prediction-hashes.json,
determinism.json, the adapter, and the benchmark integration patch — are
committed under
examples/benchmarks/opendataloader-bench/7af1d8f4….
No source PDFs, ground truth, or predicted Markdown are redistributed. The
benchmark-only output-schema adapter lives in
validation/benchmarks/opendataloader_bench/adapter.py
and never changes CocoaPDF's default conversion.
How it works
Every output is generated from one reconciled semantic document graph:
PDF bytes and operators
│
▼
COS objects, streams, resources, fonts, glyphs,
graphics, images, annotations, forms, and tags
│
▼
Normalized source representation
│
▼
Layout, regions, reading order, and page structure
│
▼
Tagged-PDF and geometric reconciliation
│
▼
Authoritative semantic document graph
├── Markdown
├── HTML
├── semantic JSON
└── report and assets
The graph may contain:
- headings and paragraphs;
- inline styles and links;
- ordered, unordered, and nested lists;
- quotations and code;
- tables, cells, captions, and notes;
- figures and preserved image assets;
- footnotes and endnotes;
- references, citations, and cross-references;
- outlines and table-of-contents entries;
- form fields and widgets;
- anchors and explicit page boundaries.
Markdown remains the preferred output. Structured HTML is used when Markdown cannot safely express table spans, nested cell content, vertical writing, dimensions, alignment, or other document semantics.
Scope and safety policy
CocoaPDF operates directly on the information already encoded in the PDF.
Supported document class
CocoaPDF is intended for:
- reports and manuals;
- academic and technical documents;
- business and financial documents;
- exported office documents;
- tagged and accessible PDFs;
- forms with existing field values;
- documents containing tables, figures, notes, references, and multiple columns.
Deliberately excluded
CocoaPDF does not:
- perform OCR;
- infer text from image pixels;
- use AI or machine-learning models;
- execute JavaScript, form actions, launch actions, or embedded programs;
- invent missing Unicode characters, cells, destinations, labels, or form values;
- submit, reset, calculate, or validate PDF forms.
Raster images are preserved as images. Their placement, dimensions, alignment, links, captions, and alternative text are retained when available.
Encrypted PDFs are refused unless their contents can be validated safely. Unsupported or malformed constructs produce warnings and conservative fallbacks rather than silent fabrication.
Capabilities
Semantic document recovery
CocoaPDF can reconstruct:
- paragraphs across visually wrapped PDF lines;
- hard and soft line breaks;
- hyphenated line wraps;
- heading levels and numbered headings;
- bold, italic, monospace, underline, strike, highlight, superscript, and subscript evidence;
- inline and fenced code;
- block quotations;
- horizontal separators;
- ordered, unordered, mixed, and nested lists;
- multiple columns, sidebars, callouts, figures, tables, and footnote regions;
- repeated headers, footers, logos, page numbers, and other page furniture.
Reading order is determined from page geometry, regions, tags, and source evidence rather than raw object order alone.
Tables
CocoaPDF supports both ruled and carefully accepted borderless tables.
Capabilities include:
- grid and lattice detection;
- precision-gated borderless table detection;
- conservative missing-border span inference;
- rowspans and colspans;
- rotated headers;
- multiline and nested cell content;
- typed table captions and notes;
- cell alignment;
- per-cell provenance, evidence, warnings, and confidence;
- guarded continuation across page boundaries;
- GFM output for simple tables;
- structured HTML fallback for tables Markdown cannot represent faithfully.
Article columns, bibliographies, aligned prose, and other table-like layouts are rejected when the evidence is insufficient.
Figures and images
CocoaPDF preserves raster images without attempting to read text from them.
It can retain:
- the original image bytes or an embedded data URI;
- PDF placement quads;
- displayed width and height;
- page alignment;
- image links;
- figure captions;
- Tagged-PDF alternative text;
- source-page and object provenance;
- repeated-asset deduplication.
A conservative vector-to-SVG approximation is available for supported vector figures.
Notes, references, and navigation
CocoaPDF can reconstruct:
- footnote and endnote references;
- note definitions and continuation blocks;
- reference and bibliography sections;
- citations;
- references to figures, tables, sections, equations, appendices, and notes;
- PDF outlines and bookmarks;
- visible tables of contents;
- named and direct destinations;
- anchors and internal links.
Targets are linked only when resolution is sufficiently reliable. Unresolved references remain readable text with diagnostic metadata.
AcroForm semantics
CocoaPDF reads AcroForm field trees without executing field actions.
Supported field semantics include:
- text fields;
- multiline values;
- choice fields;
- selected options;
- checkboxes;
- radio buttons;
- push-button identification;
- signature fields;
- inherited field attributes;
- widget provenance;
- password-value redaction.
CocoaPDF never submits, resets, calculates, validates, imports, launches, or executes a form action.
Tagged PDF support
Tagged-PDF information is treated as a strong semantic prior and checked against page geometry and marked-content ownership.
Supported structures include:
StructTreeRoot;- global and namespace
RoleMap; ClassMap;ParentTree;StructParentsandStructParent;- MCIDs;
- MCR and OBJR references;
/Pgand/Stm;/ActualText;/Alt;/E;/Lang;- artifact markers;
- structure attributes;
- list numbering;
- table row and column spans.
Reconciliation can materialize tagged:
- headings;
- paragraphs;
- lists;
- tables;
- figures;
- captions;
- links;
- TOC entries;
- notes;
- artifacts.
Broken or incomplete tag trees fall back to geometric reconstruction rather than overriding credible page evidence.
PDF and text foundation
PDF object, stream, graphics, and font support
PDF structure
- Classic cross-reference tables.
- Cross-reference streams.
- Hybrid and incremental chains.
- Object streams.
- Indirect stream lengths.
- Page trees and inherited resources.
- Content arrays.
- Form XObjects.
- Stream-aware malformed-file recovery.
- Configurable object, recursion, decompression, glyph, path, and image limits.
Stream filters
- Flate.
- ASCII85.
- ASCIIHex.
- RunLength.
- LZW.
- Pass-through handling for supported image filters.
Content and graphics
- Text-state operators.
- Geometry and transformation matrices.
- Paths and painted rectangles.
- Clipping bounds.
- Graphics-state alpha.
- Images and image masks where safely representable.
- Form recursion protection.
- Link and non-link annotation metadata.
- Marked-content properties.
- Inline images.
Fonts and Unicode
- Standard-14 fonts and metrics.
- PDFDocEncoding.
- WinAnsi and Differences encodings.
- ToUnicode CMaps.
- Composite CID fonts.
- Selected predefined Unicode CMaps.
- Ligature normalization.
- Vertical
DW2andW2metrics. - Geometry-derived spacing.
TJdisplacements.- Duplicate and faux-bold suppression.
- Invisible-text handling.
- Unicode bidirectional reordering.
Bidirectional and vertical text
CocoaPDF includes source-preserving bidirectional processing for mixed left-to-right and right-to-left text.
The implementation handles:
- paragraph direction;
- explicit embeddings and overrides;
- directional isolates;
- weak and neutral resolution;
- paired-bracket behavior;
- implicit embedding levels;
- visual line reordering.
Vertical writing support includes:
- vertical CMaps;
- vertical glyph origins and displacements;
DW2andW2metrics;- vertical
TJmovement; - vertical geometry;
- loss-aware HTML using vertical writing modes.
The repository includes a checker for the official Unicode BidiCharacterTest.txt and BidiTest.txt corpus formats.
Outputs
Markdown
Markdown output is CommonMark-oriented and uses GFM-compatible tables where appropriate.
Generated HTML is inserted only where Markdown cannot safely preserve the original structure, such as:
- rowspan or colspan tables;
- nested cell content;
- vertical text;
- image sizing and alignment;
- complex figures;
- unsupported native Markdown semantics.
HTML
HTML is emitted directly from the semantic graph rather than being reconstructed from Markdown.
This preserves:
- typed sections and headings;
- semantic lists;
- table structure;
- cell spans;
- captions and notes;
- figures;
- form semantics;
- anchors and internal navigation;
- vertical writing;
- source and diagnostic metadata where configured.
JSON and reports
Semantic JSON exposes the document graph in a machine-readable form.
Reports can include:
- semantic nodes;
- source references;
- source pages and regions;
- glyph identifiers;
- MCIDs;
- PDF object references;
- bounding boxes;
- confidence;
- evidence;
- warnings;
- page processing modes;
- extracted assets;
- graph-validation results;
- low-confidence decisions.
For image nodes, the report explicitly records:
{
"ocr_used": false,
"text_extraction_attempted": false
}
Installation
Native downloads
Use the platform buttons at the top of this README to download the latest published release.
The published release packages are:
cocoapdf-windows-x86_64.zip
cocoapdf-linux-x86_64.tar.gz
cocoapdf-macos.tar.gz
The macOS package contains separate Apple Silicon and Intel executables. The Linux x86_64 binary uses an Ubuntu 22.04 build baseline for broader glibc compatibility.
Before execution, verify the package against SHA256SUMS.txt and inspect its per-binary provenance in RELEASE.json. Downloads are intentionally lean: Windows and Linux contain one executable, the MIT license, and the exact third-party notices captured by that build; macOS contains its Apple Silicon and Intel executables, the MIT license, and notices for both runtimes. The Windows executable embeds the CocoaPDF icon and product/version metadata.
Install from source
CocoaPDF requires Python 3.9 or later and has no runtime dependencies.
python -m pip install .
Run from the repository
Linux and macOS:
export PYTHONPATH=src
python -m cocoapdf.cli input.pdf
Windows PowerShell:
$env:PYTHONPATH = "src"
python -m cocoapdf.cli input.pdf
The repository launcher is equivalent:
python run_cocoapdf.py input.pdf
Usage
Common conversions
# Convert to Markdown and print to stdout
cocoapdf input.pdf
# Write Markdown, extracted assets, and a diagnostic report
cocoapdf input.pdf \
-o document.md \
--assets assets \
--report report.json
# Produce semantic HTML
cocoapdf input.pdf \
--format html \
-o document.html
# Produce a Markdown, HTML, JSON, and report package
cocoapdf input.pdf \
--format both \
-o output
# Produce a JSON envelope containing the graph, report, Markdown, and HTML
cocoapdf input.pdf \
--format json \
-o result.json
# Convert selected pages and preserve explicit page boundaries
cocoapdf input.pdf \
--pages 1,3-5 \
--page-breaks \
-o excerpt.md
When --format both targets a directory, CocoaPDF writes:
output/
├── document.md
├── document.html
├── document.json
└── report.json
Referenced assets are written to the directory supplied through --assets.
Image handling
# Extract image files and reference them from the output
cocoapdf input.pdf \
--image-mode reference \
--assets assets
# Embed image bytes as data URIs
cocoapdf input.pdf \
--image-mode embed
# Preserve dimensions and alignment inside the Markdown file when needed
cocoapdf input.pdf \
--image-markup auto
# Native Markdown image syntax (default)
cocoapdf input.pdf \
--image-markup markdown
# Force generated HTML figure and image markup
cocoapdf input.pdf \
--image-markup html
--image-markup markdown is the default. The Markdown projection stays portable,
while CocoaPDF's independent HTML projection still preserves figure dimensions,
alignment, captions, placement, and links. Use auto or html only when that
controlled HTML must also be embedded in the Markdown file itself.
Independent HTML projection
Markdown and HTML are sibling projections of the reconciled semantic graph. HTML is not produced by converting CocoaPDF's Markdown back into a document. The HTML renderer emits native headings, sections, lists and disabled task controls, figures and captions, table header scopes and spans, footnote and bibliography roles, language and direction attributes, documentary form fields, MathML, and responsive/print CSS. Semantic elements also carry stable node, confidence, and source-page data attributes for inspection. If the rich HTML renderer fails, the emergency path emits only escaped text from the semantic graph; it does not fall back to reparsing Markdown.
A closed allowlist retains internally generated HTML-only fragments when the typed graph cannot yet represent their complete geometry, including styled column and callout containers and printed form appearances. PDF text is still escaped, unsafe link schemes are dropped, PDF actions are never executed, and AcroForm extraction does not create a submit-capable browser form.
Markdown keeps its established lossless layout reconciliation path. Changes to HTML projection therefore cannot rewrite Markdown bytes.
Python API
from cocoapdf import ConvertOptions, convert_file
result = convert_file(
"input.pdf",
ConvertOptions(
assets_dir="assets",
image_mode="reference",
image_markup="auto",
page_breaks=False,
),
)
print(result.markdown)
print(result.html)
semantic_document = result.semantic
semantic_json = semantic_document.to_dict()
report = result.report
A single conversion result contains:
result.markdown
result.html
result.semantic
result.report
result.assets
result.warnings
Diagnostics and explainability
CocoaPDF is designed to make uncertain decisions visible.
# Write a detailed report and print explanations
cocoapdf input.pdf \
--report report.json \
--explain
# Surface semantic nodes below a confidence threshold
cocoapdf input.pdf \
--show-low-confidence \
--min-confidence 0.85
# Explain the reconstructed document
cocoapdf explain input.pdf
# Trace a page through the extraction pipeline
cocoapdf trace input.pdf --page 1
# Draw a page-region overlay
cocoapdf overlay input.pdf --page 1 -o overlay.svg
# Inspect PDF objects, resources, and interpreted content
cocoapdf inspect input.pdf
Additional diagnostic commands include:
cocoapdf diff expected.md actual.md
cocoapdf score v1
cocoapdf bench v1
Every accepted non-container semantic node is expected to carry at least one source reference containing a page number and, where available:
- glyph IDs;
- region IDs;
- MCIDs;
- PDF object references;
- bounding boxes.
Graph-validation errors are reported rather than silently discarded.
Development and verification
Required verification gate
GitHub Actions enforces this gate on every pull request targeting main and again on every update to main. A merge cannot rely on the checklist alone: branch protection requires the Version policy, both endpoint-version Quality checks (Python 3.9 and 3.13), and all four native Binary checks to pass.
python -m pip install --disable-pip-version-check -e .
python scripts/check_repository_invariants.py
python -m unittest discover -s tests -v
python -m compileall -q src tests tools scripts
python -m cocoapdf --version
Unicode bidirectional verification
python tools/check_unicode_bidi.py /path/to/BidiCharacterTest.txt
python tools/check_unicode_bidi.py /path/to/BidiTest.txt
The checker exits with a non-zero status when it finds paragraph-level, resolved-level, or visual-order mismatches. It also records the Unicode database version used by the running Python interpreter.
Development method
CocoaPDF follows a generate–inspect–verify workflow:
- Create known Markdown, HTML, Typst, LaTeX, or office-document sources.
- Generate PDFs through materially different producer engines.
- Inspect objects, streams, operators, fonts, glyphs, graphics, tags, and layout.
- Convert each PDF through CocoaPDF.
- Compare normalized semantic output with locked expected output.
- Add adversarial near-miss fixtures before changing a detector.
- Run the complete regression and resource-limit suite after every correction.
The objective is not to optimize for one showcase PDF. Each change must improve general PDF behavior without silently damaging another producer dialect.
Semantic detector changes must include positive evidence, an adversarial near-miss, and provenance/confidence assertions where applicable. Producer- or fixture-specific shortcuts are not accepted.
Releases
CocoaPDF uses semantic version numbers in the form:
MAJOR.MINOR.PATCH
Every accepted update to main is versioned, tested, built natively, smoke-tested, and published automatically. The release class is selected as follows:
- compatible fixes use
release:patch, afix:PR title, or afix/,bugfix/,hotfix/, orpatch/branch and incrementPATCH; - all other compatible changes use
release:minorby default and incrementMINORwhile resettingPATCHto zero; MAJORcan change only when the repository owner incrementsVERSION_MAJORby exactly one and applies thebreakinglabel; automation then publishesMAJOR.0.0.
Published releases include:
- native Windows, Linux, and macOS packages;
- per-binary provenance manifests;
RELEASE.json;SHA256SUMS.txt;- source archives;
- release notes.
Until platform signing and notarization are available, users should verify published checksums when binary provenance matters.
Project principles
- Semantic fidelity over visual text dumping.
- PDF-native evidence before heuristic inference.
- Geometry validates tags; tags inform geometry.
- Markdown when sufficient, HTML when necessary.
- One semantic graph for every output.
- No OCR or text guessing from images.
- No AI or machine-learning dependency.
- No fabricated Unicode or document structure.
- Low-confidence decisions remain inspectable.
- Deterministic output from identical inputs and options.
License
CocoaPDF is released under the MIT License.
The installable package declares no runtime dependencies: conversion uses only
Python's standard library and CocoaPDF code. Optional standalone builds use a
pinned PyInstaller release; its Bootloader Exception allows bundling without
requiring CocoaPDF source to be relicensed. Distributions remain multi-license
artifacts and carry their notices. Project attribution is available in
NOTICE; incorporated data and standalone-runtime licenses are
recorded in THIRD_PARTY_NOTICES.txt, and release
archives carry the exact CPython and PyInstaller license texts verified by each
native build.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cocoapdf-0.10.3.tar.gz.
File metadata
- Download URL: cocoapdf-0.10.3.tar.gz
- Upload date:
- Size: 522.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
53eb2c1a3ff1e3a5d4f9d2a9476c2753a8bc37ee0f2585a58f4b189e27f3cb5a
|
|
| MD5 |
31ada2e497aae45776baf1b716ee6212
|
|
| BLAKE2b-256 |
34e2da0258a606ccafa6ed3f0ff586636d9960d214d3c3f7e5645f782cb1f7e1
|
File details
Details for the file cocoapdf-0.10.3-py3-none-any.whl.
File metadata
- Download URL: cocoapdf-0.10.3-py3-none-any.whl
- Upload date:
- Size: 344.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0fede6469828cc0de1966e77cf4357731b4ad86e63bc3e37e44730e35c26be3d
|
|
| MD5 |
12ed3e8418d256b8502e2c0367d0e789
|
|
| BLAKE2b-256 |
19ce6afe77373b8d4673ea4c7b4926f38e340051c44795ac383ecd22fce8ad76
|