Python resume parser: the libraries that work, and the code
Published
If you want a Python resume parser today, the short answer is that the library everyone links to is not maintained, the library that ranks first on GitHub is not the one pip install gives you, and the one tool in this space that is genuinely well kept does not extract resume fields at all. This article is the map: what each option actually returns, the code to run it, and the point where a developer is better off calling a parsing API than owning an NLP stack. Every version and date below was read from PyPI, GitHub or the project's own page as of September 2026.
We build ResumeJSON, a per-parse resume parsing API, so read this as written by an interested party. The library facts are checkable in one pip index — do check them, because the dates are the whole argument.
The Python resume parser libraries, compared
| Library | Latest release | Python support it declares | What it returns | Maintained? |
|---|---|---|---|---|
| pyresparser | 1.0.6, 15 December 2019 | 3.3 – 3.7 (its own classifiers) | A fixed dict: name, email, phone, skills, degree, college, designation, companies | No release in nearly seven years |
| pydparser | 1.0.4, 27 December 2023 | >= 3.10 | Same shape, plus job-description parsing | Two years since its last release |
| resume-parser | 0.8.4, 26 December 2021 | Unspecified | A resume dict, spaCy + NLTK based | Nearly five years quiet |
| Docling | 2.128.0, 16 September 2026 | >= 3.10, < 4 | Structured document — headings, tables, reading order | Yes, actively |
| pdfplumber | 0.11.10, 15 June 2026 | >= 3.8 | Raw text, words, tables, character boxes | Yes |
| spaCy | 3.8.16, 24 August 2026 | >= 3.9, < 3.15 | Nothing resume-shaped on its own — the NLP toolkit the others build on | Yes |
Two columns do the work here. "Latest release" is the risk you are taking on, because a resume parser is a pile of heuristics about how humans format documents, and those formats keep moving. "What it returns" is the gap you will be filling yourself: the maintained tools give you a clean document, not a candidate record.
The pyresume trap, before you install anything
Search python resume parser and one of the first results is a GitHub repository called pyresume, described as "A simple, accurate resume parser for Python". It is real — wespiper/pyresume, MIT licensed, last pushed 3 August 2025 as of September 2026 — but it is a small project, and more importantly it is not what pip install pyresume installs.
The pyresume package on PyPI is version 0.1.3, uploaded 12 June 2018, from a different author entirely, and its own summary says what it is:
Populate a predefined LaTeX template with contents defined in YAML to build your resume.
That is a résumé builder, not a parser. Two unrelated projects, one name, and the search result and the install command point at different ones. Check the PyPI project URL against the repository you meant before you add anything here to requirements.txt.
What pyresparser actually gives you
pyresparser is the library nearly every tutorial on this topic uses, so it is worth being precise rather than dismissive. Its documented usage is two lines:
from pyresparser import ResumeParser
data = ResumeParser('/path/to/resume/file').get_extracted_data()What comes back is a dict with a fixed key set — name, email, mobile_number, skills, degree, college_name, designation, company_names, no_of_pages and experience fields. For a screening script that needs a name, an email and a skills list, that is genuinely enough, and 960 GitHub stars say plenty of people shipped it.
The problem is underneath. Its PyPI metadata declares support for Python 3.3 through 3.7, and it depends on spacy (>=2.1.4) with no upper bound — so pip will happily resolve a 2019 library against spaCy 3.8, which changed its pipeline API. Its install instructions ask you to download a spaCy model and NLTK word lists separately, its own notes warn that on Windows you can only extract .docs and .pdf files, and the repository was last pushed 13 September 2023 with 45 issues open. None of that makes it useless. It makes it a 2019 snapshot you are adopting and maintaining, not a dependency somebody else is keeping current for you. Budget for the pinning afternoon before you budget for the parsing.
pydparser is the pragmatic fork of exactly this problem: same shape, and its own summary says it is "compatible with python 3.10". It last released 27 December 2023, so it is the same bet, two years fresher.
Extracting the text is the easy half
A lot of "build a resume parser in Python" tutorials are really PDF-extraction tutorials. That part is solved and well maintained:
import pdfplumber
with pdfplumber.open("resume.pdf") as pdf:
text = "\n".join(page.extract_text() or "" for page in pdf.pages)Docling goes further, and its own quickstart is as short:
from docling.document_converter import DocumentConverter
converter = DocumentConverter()
result = converter.convert("resume.pdf")
print(result.document.export_to_markdown())Docling describes itself as an SDK for "parsing PDF, DOCX, HTML, and more, to a unified document representation" — headings, tables and reading order preserved. It released 2.128.0 on 16 September 2026, which tells you how alive it is compared to everything in the first half of the table.
But notice what you have after either snippet: text. Not work[0].company, not a normalised date range, not a skills array. Turning that text into a candidate record is the part that takes the weeks — name disambiguation, employment date ranges written eleven different ways, education blocks that look exactly like employment blocks, skills that are section headings. That is the half nobody's README covers, and it is the half that decides whether your ATS import is trustworthy.
Who should stay with a Python library
A hosted API is not the right answer for everyone, and there are three cases where staying in-process is clearly correct:
- The documents cannot leave your network. If your compliance position is that candidate CVs are not sent to a third party, that settles it — run pdfplumber or Docling locally and write the field extraction yourself.
- You need the intermediate representation, not the fields. Search indexing, redaction, layout analysis, an LLM pipeline of your own: Docling is built for exactly that and is a better tool for it than any resume endpoint.
- Volume is tiny and "good enough" really is. A few hundred CVs, one recruiter, a name and an email — pyresparser's two lines will do it, and paying anything is silly.
If none of those are you, the calculation changes, because what you are actually buying is somebody else's maintenance of the heuristics.
When calling an API is the cheaper answer
The honest comparison is not library-versus-API on features. It is your time against a per-parse price. A self-hosted stack costs you the spaCy pin, the model downloads in your Docker image, the date-range edge cases, and a re-test every time a resume template trend changes. A parsing API costs a request.
Here is the same job against ResumeJSON, which returns typed JSON — basics, work, education, skills, certifications, languages and total_years_experience — in about 2.2 seconds:
import requests
resp = requests.post(
"https://resumejson-resume-cv-parser-api.p.rapidapi.com/v1/parse",
headers={
"x-rapidapi-key": "YOUR_KEY",
"x-rapidapi-host": "resumejson-resume-cv-parser-api.p.rapidapi.com",
"content-type": "application/json",
},
json={"text": text}, # or send a file — base64 or multipart
timeout=30,
)
resume = resp.json()["resume"]
print(resume["basics"]["name"], resume["total_years_experience"])No model downloads, no spaCy version, nothing to pin. Uploads are accepted to 20 MB and 60,000 characters of text; past either you get a 413 naming the limit rather than a silent truncation.
| Self-hosted Python library | ResumeJSON | |
|---|---|---|
| Setup | pip, spaCy model, NLTK data, pinning | One HTTP call |
| Field mapping | Yours to write and keep | Typed JSON, documented in the field reference |
| Cost at 100 CVs/month | Your time | $0 — the free rung is a hard cap |
| Cost at 1,000 CVs/month | Your time | $29/month, or $0.05 a parse pay-per-use |
| Keeps working when formats drift | If you maintain it | Our problem |
| Runs offline | Yes | No |
That last row is the real trade, and it is why the "stay with a library" list above is not a formality.
Try it before you decide
You do not need a key to see the output shape: the free browser parser runs a real CV through the same endpoint, and the field reference is generated from the API's own schema, so it cannot drift from what you will receive. If you are weighing build against buy more broadly, open source resume parser: what works, and when to buy instead covers the non-Python options too, and Textkernel pricing covers the enterprise end of the market.
Whichever way you go, decide it on the release dates rather than the star counts. A parser is a maintenance commitment, and in this corner of PyPI most of the well-known ones stopped being maintained years before the resumes did.