pdfannots: turning an annotated PDF into a reviewer's comment list
Extracts and formats text annotations from a PDF file
At a glance
- What is it?
- pdfannots extracts highlights, comments and formatting marks from a PDF and prints them as Markdown or exports them as JSON, sorting them into highlights, detailed comments and nits so that a scientific paper review reads in the right order. The extraction quality is bounded by pdfminer, and the documentation is unusually candid about the ways it fails.
- Who is it for?
- pdfannots suits a reviewer, editor or author who has an annotated PDF and needs the comments as text they can read, paste or post, particularly for conference and journal submissions where the annotated PDF is the input format. It is the wrong tool if you need a faithful rendering of the document, since it extracts annotation text rather than reproducing the page, and it is unreliable on multi-column layouts unless you help it with the column parameter.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 9 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A reading tool for peer review workflows
pdfannots extracts annotations, highlights, comments and similar marks, from a PDF file and formats them as Markdown or exports them to JSON. The intended use is stated plainly: reviewing submissions to scientific conferences and journals. That context explains the design, because in that workflow the annotated PDF is what the reviewer sends back, and the receiving author then has to read the comments out of a visual document. Reading them means scrolling through pages, reconstructing which comment belongs to which passage, and separating the substantive remarks from the punctuation fixes. The tool turns that back into a linear list. The audience is therefore the people handling peer review on either side, plus anyone who has inherited a pile of annotated PDFs and needs the content as text rather than as an image of a page.
The default output is sorted into three tiers
The Markdown format is not a flat dump of annotations, and the ordering is the point. Highlights without an attached comment come first, as highlights with just the highlighted text. The README is candid that these are not typically suitable for use in a review, since they are unlikely to mean anything to the recipient, and that they exist mainly as a reminder to the reviewer. Next come highlights with an attached comment and text annotations that are not attached to any particular text or highlight, output as detailed comments, and the README notes that most comments on a reviewed paper are of this form. Last come the underline, strikeout and squiggly underline annotations, output as nits, with or without an attached comment. The stated intention is to separate formatting and grammatical corrections from more substantial comments about the content. For a human reading a review, that triage is the useful part, and it is why the order is fixed rather than the order the annotations happen to appear in the file.
Page numbers and embedded outlines anchor each entry
Each annotation is reported with its page number and, where there is one, the associated highlighted or underlined text. On top of that, the tool uses a property of the document itself. If the PDF embeds outlines, also known as bookmarks, such as those generated by the LaTeX hyperref package, those are printed to help identify which section of the document an annotation refers to. That is a small but decisive feature for academic PDFs, since a reviewer working in a multi-section paper writes comments like this paragraph is unclear without a way to locate the paragraph, and a bare line number is much less useful than a section reference. It also means the quality of the location information depends on the document having been produced with sensible bookmark structure, which is a property of how the PDF was generated rather than of the tool.
Installing it and running the first extraction
The installation is a single command from PyPI:
python3 -m pip install pdfannotsThe requirements are Python 3.9 or newer and pdfminer.six, and the manifest pins the dependency as pdfminer.six with a floor of the 20220319 release and the 20240706 release excluded. The requirements file in the repository shows how that resolves in practice, with a different pin for Python 3.9 than for later versions:
# general requirements for pdfannots
# Use as: pip3 install -r requirements.txt
pdfminer.six == 20251107 ; python_version == "3.9"
pdfminer.six == 20251230 ; python_version > "3.9"The tool is exposed as a console script named pdfannots, and the README says to run pdfannots --help for the options and the invocation, noting that in a source tree the equivalent is pdfannots.py --help. The repository root holds both a pdfannots.py script and a pdfannots/ package directory, so the two forms exist side by side for development and for installation.
pdfminer is where the output can go wrong
The known issues section is the most useful part of this README, because the failure modes are real and named. The underlying parser, pdfminer, is not infallible at extracting text from a PDF. Sometimes it misses or misplaces individual characters, which results in annotations with some or all of the text missing, and in the worst case you see a warning. Sometimes the characters are captured but the spaces between the words are not, and the suggested fix is to tweak the advanced layout analysis parameters, for example the word margin option. And sometimes it extracts all the text but renders it out of order, for example reporting that text at the top of a second column comes before the text at the end of the first column. That last failure is the nastiest, because it makes pdfannots return the annotations out of order or report the wrong outline for an annotation. The documented workaround is to force a fixed page layout with the columns parameter, for example two columns for a typical two-column document.
Whitespace-only annotations and joined hyphens
Two more behaviours are worth knowing before you trust an output. If an annotation, such as a strikeout, covers solely whitespace, no text is extracted for it and the annotation is skipped with a warning. The README attributes this to the way pdfminer reports whitespace, which has only an implicit position defined by the surrounding characters. So a strikeout that covers a space rather than a word simply disappears from the report. The second behaviour is a deliberate text transformation. When extracting text, pdfannots removes all hyphens that immediately precede a line break and joins the adjacent words. This usually produces the best results with LaTeX multi-column documents, where a hyphenated word split across lines should be one word, but sometimes the hyphen needs to stay, and the tool cannot tell the difference. The example given is a memory-mapped word that comes out as one concatenated token. The escape hatch is the keep-hyphens flag, which disables the behaviour.
Output formats live in Printer subclasses
The FAQ explains how to change the output. Minor tweaks, such as word wrap, or skipping or reordering output sections, can be done with command line arguments. Anything more elaborate means editing the relevant Printer subclass, since all of the output comes from there, and pull requests introducing new output formats or variants as printers are welcomed. That is the extension point to know about if you want a different shape of report, for instance one that separates the nits further or that emits a summary table. The project is MIT licensed, with the licence file named LICENSE.txt and the manifest pointing at it, and the manifest also carries the MIT classifier, the Intended Audience of Science/Research and the Topic of Text Processing. The build uses hatchling with the version read from the package, and the mypy configuration is strict, with a long list of disallow rules. The release line is v0.5 from 2025-01-08, after v0.4 in 2023 and v0.3 in 2022, and the last push to the main branch was on 2026-10-16.
Editorial conclusion
pdfannots suits a reviewer, editor or author who has an annotated PDF and needs the comments as text they can read, paste or post, particularly for conference and journal submissions where the annotated PDF is the input format. It is the wrong tool if you need a faithful rendering of the document, since it extracts annotation text rather than reproducing the page, and it is unreliable on multi-column layouts unless you help it with the column parameter. Before trusting an output, check the warnings it prints about missing text and skipped whitespace-only annotations, and read the LICENSE.txt file, which the manifest points to as the licence text.
Frequently asked questions
How do I install pdfannots and run it?
Install it from PyPI with python3 -m pip install pdfannots. It needs Python 3.9 or newer and pdfminer.six, and the command pdfannots --help lists the options, with pdfannots.py --help being the equivalent in a source tree.
Why are my annotations coming out in the wrong order?
The underlying pdfminer parser sometimes extracts all the text but renders it out of order, for example in multi-column layouts, which makes pdfannots return annotations out of order or attach the wrong outline. The documented workaround is to force a fixed layout with the columns parameter, for example --cols=2.
How do I stop pdfannots from joining words split across lines?
By default the tool removes hyphens that immediately precede a line break and joins the adjacent words, which is usually right for LaTeX documents but can turn a compound word into one token. Pass the keep-hyphens flag to disable that behaviour.
Can I change the format of the pdfannots output?
Small tweaks such as word wrap or reordering sections can be done with command line arguments, while larger changes mean editing the relevant Printer subclass, since all output comes from there. Pull requests that add new output formats as printers are welcomed.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/0xabu-pdfannots)Was this useful?