Parse a Resume to JSON in Python
No spaCy, no models, no GPU: the extraction happens server-side. Your Python's whole job is uploading a file and reading JSON. Two ways to do it below; both fit in one screen.
To parse a resume in Python, POST the file to the SharpAPI parse_resume endpoint and poll the returned status URL until the job succeeds. The response carries 50+ structured fields. Total code: under 30 lines with requests, under 10 with the official SDK.
Option 1 — the official SDK
Install once, and the polling loop disappears:
from sharpapi import SharpApiService
sharp_api = SharpApiService(api_key='YOUR_SHARP_API_KEY')
status_url = sharp_api.parse_resume(
file_path='resumes/candidate.pdf',
language='English', # optional
)
parsed_resume = sharp_api.fetch_results(status_url)
print(parsed_resume.get_result_json())
Option 2 — plain requests, full control
If you would rather see the whole HTTP conversation — or you are wiring this into an existing client — the raw flow is two calls:
import time
import requests
API_KEY = 'YOUR_SHARP_API_KEY'
HEADERS = {'Authorization': f'Bearer {API_KEY}'}
# 1. Submit the file — returns 202 + a status URL immediately
with open('resumes/candidate.pdf', 'rb') as fh:
submit = requests.post(
'https://sharpapi.com/api/v1/hr/parse_resume',
headers=HEADERS,
files={'file': ('candidate.pdf', fh, 'application/pdf')},
data={'language': 'English'},
)
submit.raise_for_status()
status_url = submit.json()['status_url']
# 2. Poll until the job finishes (typically a few seconds)
while True:
job = requests.get(status_url, headers=HEADERS).json()
if job['data']['attributes']['status'] in ('success', 'failed'):
break
time.sleep(2)
result = job['data']['attributes']['result']
print(result['candidate_name'])
for position in result['positions']:
print(f"- {position['position_name']} @ {position['company_name']}")
What comes back
result is the full deterministic schema — candidate profile, positions[] with per-role skills, education_qualifications[] with normalized degrees, plus derived signals like years_of_experience. Explore the complete payload before you write your models — one Pydantic class covers every response.
Production notes
- Skip polling at scale. Pass a webhook URL with the submission and receive results push-style — essential once you parse in bulk.
- Handle the failed status. Corrupt files and password-protected PDFs fail cleanly; log the job id and move on.
- Photos work too. JPG/PNG/TIFF go through the same call — OCR is server-side, so the code above already handles scanned resumes.
Questions, answered
Is there an official Python SDK for resume parsing?
Yes — pip install sharpapi gives you SharpApiService with a parse_resume(file_path, language) method and a fetch_results(status_url) helper that handles the polling loop for you.
Do I need any ML or NLP libraries installed?
No. The extraction runs server-side; your Python code only uploads a file and reads JSON. The requests library — or the SDK — is the entire dependency footprint.
How do I handle the asynchronous flow in Python?
The POST returns a status URL immediately. Poll it every second or two until status is success, or skip polling entirely by passing a webhook URL and receiving the result push-style.