DEV Community

Cover image for Hidden Characters That Break ATS Keyword Matching
Muhammad Ali Mughal
Muhammad Ali Mughal

Posted on

Hidden Characters That Break ATS Keyword Matching

A resume can read perfectly to a human and still fail a keyword search, because the recruiter's search box never sees what you see. It sees code points. A zero-width space pasted from a web page, a "fi" ligature copied out of a PDF or a ♯ sign that only looks like # will split or disguise the exact keyword the job asks for. Nothing looks wrong on screen, and nothing tells you it happened.

I build Smart Resume Analyzer, an ATS resume checker, and invisible characters are one of the quieter failures I keep finding in uploaded files. I wrote this with help from AI tools and checked every command and claim myself. The test output below comes from files I generated and ran today with python-docx 1.2.0, LibreOffice 25.2 and pdftotext 25.03.

Why does my resume fail keyword matching when the word is clearly there?

Direct answer: Because the text the ATS stores is not the text you see. Characters such as zero-width spaces, soft hyphens, non-breaking spaces, typographic ligatures and look-alike symbols change the underlying string, so "Kubernetes" or "fintech" no longer matches the recruiter's query. Extract your file to plain text, find any non-ASCII characters and retype them.

The six characters I see most often

They come from normal habits: copying from LinkedIn or a job ad, pasting from an old PDF, or Word autocorrect.

Character Code point Where it usually comes from What it looks like What it does to a keyword
Zero-width space U+200B Copying from web pages, CMS editors, chat apps Nothing at all Splits "Kubernetes" into two strings
Soft hyphen U+00AD Word hyphenation, pasted web text Nothing, or a hyphen at a line end Splits "PostgreSQL" invisibly
No-break space U+00A0 Ctrl+Shift+Space in Word, web copy A normal space "GitHub Actions" stops matching a phrase search
fi / fl ligature U+FB01 / U+FB02 Copying text out of a typeset PDF "fi" "fintech" becomes an unknown word
Music sharp sign U+266F Symbol pickers, autocorrect, some fonts # "C♯" never equals "C#"
En dash in ranges U+2013 Word AutoFormat A short dash Usually fine for dates, but worth knowing it is there

The test: one resume, two versions

I made two Word files with identical visible text: a skills line and a role line. The "clean" file was typed by hand. The "dirty" file had the characters above inserted where they typically land after copy and paste. Then I ran each through two paths: the raw DOCX text (what a parser reading the Word XML gets) and a LibreOffice PDF export run through pdftotext. Last, I checked five keywords with a plain lowercase substring search, the simplest thing a keyword filter can do.

== clean.docx -> raw text
  keyword hits: kubernetes=Y postgresql=Y github actions=Y c#=Y fintech=Y
== dirty.docx -> raw text
  keyword hits: kubernetes=N postgresql=N github actions=N c#=N fintech=N
  U+00A0 NO-BREAK SPACE
  U+00AD SOFT HYPHEN
  U+200B ZERO WIDTH SPACE
  U+2013 EN DASH
  U+266F MUSIC SHARP SIGN
  U+FB01 LATIN SMALL LIGATURE FI
Enter fullscreen mode Exit fullscreen mode

On screen, both files were identical. The dirty DOCX matched none.

The PDF path was more forgiving, but not fully:

== dirty.pdf -> pdftotext
  keyword hits: kubernetes=Y postgresql=Y github actions=Y c#=N fintech=N
  U+2013 EN DASH
  U+266F MUSIC SHARP SIGN
  U+FB01 LATIN SMALL LIGATURE FI
  tokens: ['senior', 'backend', 'engineer', '2021', '2024', 'led', 'ntech', ...]
Enter fullscreen mode Exit fullscreen mode

The PDF export dropped the zero-width space and soft hyphen and turned the no-break space into a plain space. The ligature and the sharp sign survived, and a simple tokenizer turned "fintech" into "ntech". So the same resume matched 0, 3 or 5 keywords depending only on file type and characters you cannot see. That is the whole problem in one result.

Unicode normalization (NFKC) on the vendor side would map "fi" to "fi" and a no-break space to a space, but it leaves zero-width spaces, soft hyphens and ♯ untouched. You cannot know what a given ATS applies, so clean the file yourself.

A brass-rimmed magnifying lens resting on a blank white sheet of paper, representing a close inspection of resume text for hidden characters
AI-generated image.

Weak vs ATS-optimized: real rewrites

The fix is mostly retyping. Here are the lines from the test, plus two other patterns I see often.

Weak (as pasted) Hidden problem ATS-optimized (retyped)
Skills: Kuber​netes, Post­greSQL U+200B and U+00AD inside the words Skills: Kubernetes, PostgreSQL
Built pipelines in GitHub Actions U+00A0 between "GitHub" and "Actions" Built pipelines in GitHub Actions (normal space)
Languages: C♯, .NET 8 U+266F instead of # Languages: C#, .NET 8
Led fintech payment APIs U+FB01 ligature from a PDF Led fintech payment APIs
➤ Reduced deploy time by 40% Decorative arrow used as a bullet Use the editor's built-in bullet list
Node․js / Vue․js U+2024 one-dot leader instead of a period Node.js / Vue.js

If your skill names include dots, hashes or plus signs (Node.js, C#, C++), check those characters first.

How the big ATS platforms handle the text

None of these vendors publish their tokenizers, so I will not pretend to know their internals. What is well documented is what happens to your file: it gets parsed into text and fields, and recruiters then search or filter that stored text.

ATS Where your text ends up Why hidden characters matter
Greenhouse Parsed resume text and candidate profile, searchable by recruiters A split keyword can drop you out of a keyword search
Workday Application fields auto-filled from your resume, plus the stored document Odd characters can carry into autofilled fields you then have to fix by hand
Lever Candidate profile with parsed resume content and full-text search Same as Greenhouse: the query and your text must match as strings
iCIMS Parsed candidate profile fields and searchable resume text Skills split by invisible characters may not land in the right field
Taleo Parsed profile used in requisition searches and screening Older parsing pipelines are less likely to clean Unicode for you

The safe assumption is simple: if the extracted text does not contain the exact keyword, do not expect it to match. For more on how parsers turn skill strings into normalized entries, see my earlier breakdown of how ATS parsers extract and normalize resume skills.

Step-by-step diagnostic checklist

This takes about ten minutes and needs no special software beyond a text editor.

  1. Export the exact file you will upload. If you send PDF, test the PDF, not the Word source.
  2. Extract plain text. Paste the whole document into a plain-text editor, or run pdftotext -enc UTF-8 resume.pdf - on macOS or Linux. You can also run it through an ATS parser preview to see the recovered text and fields side by side.
  3. Search for non-ASCII characters. In VS Code, search with regex [^\x00-\x7F] to highlight every one. On the command line: grep -nP '[^\x00-\x7F]' resume.txt.
  4. Name each odd character. Paste anything suspicious into a Unicode inspector, or run python3 -c "import unicodedata,sys;[print(hex(ord(c)),unicodedata.name(c,'?')) for c in sys.argv[1]]" 'C♯'.
  5. Retype every keyword in your skills section by hand. Do not paste from the job ad, LinkedIn or an old PDF. This alone removes most problems.
  6. Replace decorative bullets (➤, ✓, ●) with the editor's own list formatting.
  7. Turn off automatic hyphenation in Word (Layout, Hyphenation, None). It is a common source of soft hyphens.
  8. Keep typographic dashes only in dates, and use the same style consistently. If you want to be extra safe, use a plain hyphen.
  9. Re-run the keyword check with the exact terms from the posting. If a word appears in your file but not in the extracted text, you have found your culprit.

This complements the layout issues in resume formatting mistakes that break ATS parsing. Formatting breaks structure; hidden characters break individual words.

Where the keywords should come from

Once the characters are clean, make sure the keywords are the right ones. Use the exact spelling the job ad uses ("PostgreSQL", not "Postgres", if that is what they wrote), and include the common abbreviation once next to the full term. My guide on tailoring resume keywords to a job description covers how to do that without stuffing.

A practical habit: keep a master resume in plain text or Markdown and generate your Word or PDF from it. Fix the text once and every export inherits it.

Frequently asked questions

Do smart quotes and apostrophes break ATS parsing?

Rarely. Curly quotes are common enough that parsers handle them, and they seldom sit inside a keyword. The risky characters are the ones inside skill names: zero-width spaces, soft hyphens, ligatures and look-alike symbols.

Is a PDF safer than a DOCX for hidden characters?

In my test, the PDF export stripped zero-width spaces and soft hyphens, so it matched more keywords than the DOCX. It still kept the ligature and the sharp sign. Clean the text first, then use whichever format the employer asks for.

How can I see invisible characters in Microsoft Word?

Turn on Show/Hide (the ¶ button). It reveals no-break spaces as a degree-like symbol and optional hyphens as a hooked mark. Zero-width spaces are still hard to see there, so the plain-text regex search is more reliable.

Will an ATS reject my resume because of one odd character?

Not usually as a whole. The risk is narrower: the keyword containing that character may not match a search or filter. If it is a core skill from the job title, that can be enough to keep you out of a shortlist.

Should I write "C#" or "C sharp" on my resume?

Write "C#" with a normal number sign, as the job ad most likely does. If you want to cover both, mention "C# (.NET)" in your skills line. Never use the music sharp symbol.

Does copying my LinkedIn profile into my resume add hidden characters?

It can. Text copied from web pages may carry no-break spaces or zero-width characters from the page's HTML. Paste into a plain-text editor first, check it, then move it into your resume.


Follow & Connect

Top comments (0)