Original research
What actually breaks resume PDF extraction.
We generated 108 resume PDFs across 12 formatting conditions and read every one back with the same library the X-Ray uses. This page publishes the whole thing: the results, the exact versions, the code, and what it does not show.
Last updated 2026-07-31
The short version
Bad formatting does not usually delete your words. It moves them. In every condition except a scanned image, at least 96.9% of the intended words came back. What collapsed was reading order: in the narrower two-column layout, 33.1% of output lines were fused out of two unrelated source lines — a phone number welded onto a job bullet.
108
PDFs generated and read back
12
formatting conditions
33.1%
lines welded, narrow two-column
3
conditions that changed nothing
The part most advice gets backwards: 3 of the 12 conditions caused no measurable damage at all, including decorative bullet glyphs and very tight line spacing — two things resume guides warn about constantly.
Method
Every document was built from the same 9 synthetic resume profiles, so the intended text is known exactly rather than inferred. Each profile was rendered once per condition with pdf-lib, then read back with PDF.js using the identical line-grouping thresholds that ship in the ATSPrep X-Ray: a new line when the vertical gap exceeds 2.5 units, and a space when the horizontal gap exceeds max(1.1, 0.22 × glyph height).
Four things were measured against that known ground truth:
- Recovery — share of intended words that came back at all.
- Order — longest-common-subsequence overlap with the intended reading order.
- Welding — share of output lines fused from two unrelated source lines. Measured only over tokens appearing exactly once in the resume, so attribution is unambiguous.
- Block integrity — whether each bullet stayed under the role it belongs to.
Welding exists because recovery could not see the failure. A two-column resume scores 97.9% recovery and still reads as nonsense, because the words are all present and in the wrong places. Recovery alone would have called that condition healthy.
Full results
Every condition, most damaged first. Percentages are means across the 9 profiles.
| Condition | Recovery | Order | Welded | Blocks |
|---|---|---|---|---|
| Scanned or exported as an image | 0% | 0% | 0% | 0% |
| Letter-spaced headings | 96.9% | 96.9% | 0% | 100% |
| Whole document letter-spaced | 96.9% | 96.9% | 0% | 100% |
| Table-style grid | 97.6% | 93.4% | 24.1% | 100% |
| Two columns, tight gutter | 97.9% | 83% | 33.1% | 100% |
| Two columns | 97.9% | 83.6% | 30.5% | 100% |
| Words positioned without spaces | 99.8% | 99.8% | 0% | 100% |
| Contact detail in the page margins | 100% | 93.7% | 0% | 100% |
| Single column, plain textcontrol | 100% | 100% | 0% | 100% |
| Very tight line spacing | 100% | 100% | 0% | 100% |
| Rotated sidebar | 100% | 100% | 0% | 100% |
| Decorative bullet glyphs | 100% | 100% | 0% | 100% |
A scanned image scores 0% on everything because there is no text layer to read. It is the only condition here that loses the document outright.
The result we did not expect
Letter-spaced headings lose text. The obvious explanation is that drawing a heading glyph by glyph breaks it, so we tested that directly: one condition letter-spaced only the headings, another drew the entire document glyph by glyph with no extra tracking.
Both scored 96.9%. If splitting glyphs were the cause, the whole-document version should have been far worse. It was not — so the damage comes from the tracking, not the splitting. Because the space threshold scales with glyph height, larger letter-spaced text is more fragile than small text, which makes a spaced-out section heading the most vulnerable line on a resume.
Conditions compared: per-character-tracking and per-character-body.
Get the data
The complete per-document results — all 108 rows, not only the aggregate above — are published as a single JSON file.
- Download the full dataset (JSON)
- Written by
pdf-lib@1.17.1, read bypdfjs-dist@6.1.200, onnode@24.13.0. Extraction behaviour changes between PDF.js releases, so the exact versions are part of the result. - Generated 2026-07-31. The run is deterministic: the same code reproduces the same table.
The corpus generator and the measurement runner live in the repository under scripts/research/. Rebuild every document and recompute every number with one command:
node scripts/research/run-study.mjsYou are welcome to reuse these figures, including commercially, with attribution to atsprep.com/research. The dataset is published under CC BY 4.0. If you rerun it and get different numbers, we want to know.
What this does not show
These limits are the reason the study is worth anything, so they are stated here rather than buried at the bottom of a PDF.
- The corpus is synthetic. All 108 files were generated rather than collected from real applicants. Every variable is controlled and no personal data is involved, but real resumes are messier than generated ones.
- One reader was tested. PDF.js is the library the X-Ray runs. Employer systems use different extractors and can behave differently.
- This measures text extraction, not hiring. It cannot tell you how any employer screens applications, and a clean extraction is not a prediction of an interview — see the methodology.
- Conditions were applied one at a time. A real resume combining three of them was not tested.
Written up in full
10 articles work through the dataset condition by condition, including the null results.
- We Generated 108 Resume PDFs to Find What Breaks Text Extraction
- What Happens When a PDF Reader Hits a Two-Column Resume
- Resume Tables Under Extraction: Same Problem, Milder Form
- Contact Details in Page Margins: Nothing Lost, Everything Moved
- Letter-Spacing Shreds Resume Headings
- Resume Bullet Characters and ATS Parsing
- How PDF Text Extraction Actually Works
- Why a Scanned Resume Returns Nothing at All
- Tight Line Spacing Did Not Break Extraction
- Resume Formatting Myths, Measured