What an ATS actually parses out of your résumé file
Before anything scores you, your file is flattened into one stream of plain text. Here is what survives that, what a parser deletes on purpose, and the two file problems that make a résumé arrive empty.
- resume
- ats
- research
Every applicant tracking system begins by turning your file into plain text. One stream, top to bottom. No columns, no sidebars, no icons, no two-tone header. Whatever a parser later decides about your experience, it decides from that stream — so the question worth asking is not "is my résumé ATS-friendly", it is "what is left of my résumé once the layout is gone".
We wrote the parser Crossing uses, so the rest of this is mostly our own measurement rather than a claim about Greenhouse's internals. Where the two differ, we say which is which.
A PDF is either text or a picture of text
This is the failure that costs people whole applications and produces no error anywhere.
A PDF can carry a text layer — actual character data with positions — or it can carry an image with no characters in it at all. Both look identical on your screen. Export from Word, Pages or Google Docs and you get the first. Scan a printed copy, photograph it, or run it through certain "convert to PDF" web tools, and you get the second.
Our extractor pulls the text layer and then checks what came back. Under 40 non-whitespace characters and we refuse the upload with That PDF has no readable text layer — it looks like a scan. That threshold exists because a scanned résumé does not return zero characters; it returns a handful of stray glyphs from a header or a page number, which is exactly enough to look like success.
Most employer boards will accept the same file without a word. The row lands in their system with an empty parsed body.
Test yours in five seconds: open the PDF and try to select a sentence with your cursor. If the selection highlights a rectangle instead of words, no parser on earth is reading it.
What a parser deletes on purpose
Multi-page résumés carry running headers and footers, and a parser that keeps them ends up with your name and phone number wedged into the middle of your work history four times.
So ours removes them. Any line shorter than 70 characters that appears on at least 60% of the pages is treated as page furniture and dropped, along with anything matching a bare page number (3, Page 3, 3 of 4).
That rule is unremarkable until you notice what it does to a common design: contact details in a repeated header. On a three-page résumé where your name and email sit at the top of every page, that block matches the furniture test and is deleted. Not from page two onward — everywhere, including page one.
Our parser also reads contact details from the first page before the strip runs, which is why this does not break Crossing. We cannot promise the next parser does the same. If your details only exist inside a repeated header, put them once in the body as well.
Two columns are not two columns
A PDF does not record "column". It records runs of text with coordinates, in the order the generator emitted them, and reassembling those into visual columns is work a parser chooses to do or not do. Ours does not. unpdf returns each page's text in content order, and that is what gets scored.
For a skills-sidebar layout the result is usually a stream where a fragment of the sidebar interleaves with a fragment of the body, over and over. Nothing is lost. The adjacency is: "React" no longer sits anywhere near the job it belongs to, and a section-aware pass looking for the heading Experience finds it in the wrong place.
We have not measured what each ATS vendor does here, and anyone telling you they have is describing a guess. The safe move is the boring one: a single column, real headings, no text boxes.
The file types that quietly do not work
Our uploader refuses four extensions by name, with an explanation instead of a generic error:
.doc— the legacy binary Word format. Re-save as.docx..pages— an Apple bundle, not a document..odt— OpenDocument..jpg,.png,.heic— a photo of a résumé.
We check magic bytes before the extension, because people rename files. A .docx that is really a PDF still parses; a .pdf that is really a JPEG still gets refused.
Employer boards vary, and some publish exactly what they will take. Workable's application form endpoint returns supportedFileTypes, supportedMimeTypes and maxFileSize per upload field, which is why Crossing can tell you the employer's own limit before you get there rather than after their page rejects a 15MB file. Greenhouse publishes no such limit anywhere in its question payload — we checked 45 live payloads across eight boards on 2 August 2026 for any key matching max, limit, length or char, at any depth, and there is none. So on a Greenhouse form we show no ceiling, because inventing one would be worse than admitting we do not know it.
What the keyword side actually reads
Once there is text, the mechanical part is a keyword scan, and it is far dumber than the folklore suggests. Ours is entirely deterministic — no model — because keyword presence is a fact about a file, not an opinion.
Three things about it are worth knowing, and they generalise:
Section headings carry weight. A term that appears under a requirements heading is worth 1.6× the same term appearing in a stray sentence, and a "nice to have" is worth 1.0×. That is our weighting, but the reason for it is universal: a recruiter's filter is built from the requirements block, because that is where the requirements are.
Abbreviations do not match. "K8s" on your résumé and "Kubernetes" in the posting are the same skill to a human and two different strings to a filter. Crossing recognises the alias and then tells you to write the long form anyway: Write "Kubernetes" literally somewhere — your résumé only uses an abbreviation, and keyword filters match exact strings.
An explicit Skills section matters. If our section splitter cannot find one, we say so, because parsers look for a labelled block before they resort to reading your bullets for nouns.
We also flag length. Under about 200 content words — real words, stopwords removed — a résumé does not have enough surface for any keyword scan to work with. Screened résumés generally run 350 to 800.
The short version
Almost every "ATS-friendly template" post is about fonts. Fonts are not the problem. The problems, in order of how much damage they do:
- A PDF with no text layer. Silent, total, and common.
- Contact details that exist only in a repeated header.
- A two-column layout that scrambles which skill belongs to which job.
- A file format nobody accepts, uploaded successfully.
- Abbreviations where the posting uses the full word.
Everything else is taste.
If you want to see what your file looks like after the flattening, Crossing shows you the parsed text and the per-posting keyword scan side by side — the same text every downstream step reads. What we do with your résumé covers where that text goes afterwards, and how to tailor a résumé without lying covers what to do about the keywords it says you are missing.