Turn PDF resumes into structured candidate data
Stop copying details out of PDFs by hand. Upload each resume and get back the candidate's contact details, skills, experience and education as structured JSON, plus scores that help you sort the pile.
Jane Doe
Backend Engineer · Example Corp · [email protected]
The challenge
Why this is hard to do yourself
Building it in-house
- Every resume has a different layout, so rules-based parsers miss or mix up sections.
- Copying names, emails and skills into a spreadsheet by hand takes hours for each role.
- Scanned and designed PDFs need OCR and careful text extraction before they can be parsed.
- Enterprise parsing tools are priced for large companies, with contracts and minimums.
With DataGuru
- Upload a PDF and get named fields back, whatever the layout.
- Process a whole folder of resumes with a short script.
- Parsing runs as an async job, so large batches don't block your app.
- Pay per resume with no contract; failed jobs are not charged.
APIs used
The DataGuru APIs behind this workflow
Use one or combine them. Every API takes a simple JSON request and returns structured JSON.
How it works
Set it up in 4 steps
- 1
Upload resumes
Send each PDF to the Resume Parser API. You get a `job_id` back straight away.
- 2
Wait for results
Poll the job until its `status` is `ready`, then read the parsed fields from `result`.
- 3
Save candidate data
Write the parsed fields to your ATS, database or a CSV.
- 4
Sort and shortlist
Use skills and scores to filter candidates and decide who to review first.
Example
Parse a folder of resumes into a CSV with Python
This script uploads every PDF in a folder, waits for each job to finish and writes one row per candidate. Resume parsing is asynchronous: submit a job, then poll it for the result.
import csv
import pathlib
import time
import requests
BASE = "https://api.dataguru.cc/api/v1/documents"
HEADERS = {"Authorization": "Api-Key YOUR_API_KEY"}
def parse_resume(path):
with open(path, "rb") as f:
res = requests.post(f"{BASE}/resume-parser/jobs/", headers=HEADERS, files={"file": f}, timeout=120)
res.raise_for_status()
job_id = res.json()["job_id"]
while True:
job = requests.get(f"{BASE}/jobs/{job_id}/", headers=HEADERS, timeout=30).json()
if job["status"] == "ready":
return job["result"]
if job["status"] == "failed":
raise RuntimeError(job["error"])
time.sleep(3)
with open("candidates.csv", "w", newline="") as out:
writer = csv.writer(out)
writer.writerow(["file", "name", "email", "phone", "skills", "strength", "completeness"])
for pdf in sorted(pathlib.Path("resumes").glob("*.pdf")):
r = parse_resume(pdf)
writer.writerow([
pdf.name, r.get("full_name"), r.get("email"), r.get("phone"),
", ".join(r.get("skills") or []), r.get("strength_score"), r.get("completeness_score"),
]){
"job_id": "3f6c1a2e-8b4d-4c1e-9a7f-2d5e6b7c8d9e",
"parser_type": "resume-parser",
"status": "ready",
"result": {
"full_name": "Jane Doe",
"email": "[email protected]",
"phone": "+1 555 0100",
"skills": [
"Python",
"Django",
"PostgreSQL",
"AWS"
],
"experience": [
{
"title": "Backend Engineer",
"company": "Example Corp",
"duration": "2021 - present"
}
],
"education": [
{
"degree": "BSc Computer Science",
"institution": "Example University"
}
],
"strength_score": 82,
"completeness_score": 90,
"recommendations": [
"Add measurable results to recent roles"
]
},
"error": null
}Example response trimmed to the fields used above. Values are illustrative.
What you get
What you can do with the data
Faster screening
Sort candidates by skills and strength_score instead of opening every PDF.
Clean ATS records
Fill candidate profiles automatically with name, email, phone, experience and education.
Searchable talent pool
Store parsed resumes so you can search past applicants by skill when a new role opens.
Completeness checks
Use completeness_score to spot resumes with missing sections before review.
Candidate feedback
Share the short recommendations with candidates or career-service users.
Other HR documents
Use the PDF to JSON API to pull named fields from cover letters, forms and certificates.
What it costs
Parsing 500 resumes a month:
$15.00 / month
500 requests × $0.03 / req on the Bulk Resume Parser API. No subscription or minimum; you only pay for successful requests.
See all pricingWho it's for
Built for teams like yours
- Recruiting teams
- Staffing agencies
- HR tech products
- Job boards
- University career services
- Hiring managers
FAQ
Frequently asked questions
file field of a multipart request.More use cases
Other things you can build
E-commerce & Retail
E-commerce price & stock monitoring
Keep a watchlist of products, check price, stock and seller on a schedule, and build a price history you can chart and alert on.
SEO & Search
SEO rank & search monitoring
Check where your pages rank for each keyword and country, watch competitors and related searches, and follow news coverage of your brand.
Social Media
Social listening & brand monitoring
Find posts that mention your brand or competitors, pull the conversation around them, and track engagement over time.
