n8n resume parser: turn every incoming CV into JSON fields
Published
An n8n resume parser is a three-part workflow: a trigger that receives the CV as a file, one step that turns the file into structured fields, and a node that writes those fields somewhere useful. n8n has no single "parse resume" node. You build the middle step yourself, and there are two honest ways to do it: extract the text with the built-in Extract From File node and hand it to an AI extraction node, or send the file to a resume parsing API with the HTTP Request node and get the fields back in one call.
This guide walks through both, start to finish, with the node settings that matter. It is written for the person who already runs n8n, for recruiting operations or for a job board's back office, and wants every CV that arrives to land as a row instead of an attachment somebody opens by hand.
We build ResumeJSON, the API used in the second option, so read the comparison as written by an interested party. Every statement about n8n below was read off n8n's own documentation in October 2026, and their docs are theirs to change.
The shape of an n8n resume parser workflow
Every version of this workflow has the same four stages. Decide each one before you open the editor.
- Trigger. Where the CV comes from: a form on your site, a file another system posts to you, or an inbox candidates email.
- Parse. How the file becomes fields: name, email, phone, work history, education, skills.
- Route. What happens when the parse fails, because some files will not be CVs and some will be unreadable scans.
- Write. Where the fields go: a Google Sheet, Airtable, a database table, or your ATS through its API.
The parse step is the only one with a real choice in it. The other three are ordinary n8n.
Step 1: get the CV into the workflow as a binary file
Both parsing options start from the same thing, a binary field on the incoming item that holds the file. Three triggers get you there.
- Form Trigger. n8n's own hosted form. Its documented element types include File, so a candidate can upload a CV straight into the workflow with no website of your own. This is the quickest way to test the whole flow end to end.
- Webhook. For files posted to you by something else: your careers page, a job board, another automation. n8n's Extract From File documentation describes exactly this case, a Webhook node receiving files from another system, and notes that you enable the Webhook's Raw body option to get a binary file out of it.
- Gmail Trigger. For the inbox candidates write to. As of October 2026 the trigger fires on "Message Received" at the Poll Times you set, can be limited by label or by a Gmail search, and fetches up to 10 emails per poll by default with a maximum of 50; the rest wait for the next cycle. Point it at a label such as
applicationsso only CV mail starts the workflow, and use the node's options to bring the attachments in as binary data.
Whichever you pick, run it once with a real CV and look at the item in the editor. You want to see a binary field, usually called data or attachment_0. Note its name, because the parse step asks for it.
Option A: Extract From File, then an AI extraction node
This is the all-in-n8n route. It uses two nodes.
First, Extract From File. Its operations, as of October 2026, are Extract From CSV, HTML, JSON, ICS, ODS, PDF, RTF, Text File, XLS and XLSX, plus Move File to Base64 String. Choose Extract From PDF, set Input Binary Field to the field name you noted, and the node puts the PDF's text into the item.
Two limits are worth knowing before you build on it:
- There is no Word operation in that list. A
.docxCV, which is a large share of what candidates send, needs another path. - The documentation says nothing about OCR. A scanned or photographed CV has no text layer, so expect a text extraction step to return little or nothing for one. Test with a scan before you trust it.
Second, the Information Extractor node. It exists to "extract structured information from incoming data", and you tell it what to extract in one of three ways: by listing attributes with descriptions, by pasting an example JSON object, or by writing a JSON Schema. For a resume, the JSON Schema route is the one that holds up, because work history and education are arrays of objects, and the schema is where you say so.
| Your schema decision | Why it matters for a CV |
|---|---|
work as an array of objects | A flat "experience" string cannot be filtered or sorted later |
| Dates as year and month fields | "Mar 2021", "03/2021" and "2021" should all arrive in one shape |
is_current as a boolean | "Present" is how candidates write it, and it breaks date math |
skills as an array of strings | A comma-joined string has to be split again in every later node |
| Nulls for missing fields | An empty string and a missing phone number should look different |
The extraction node calls a language model you connect and pay for, so this route puts you in charge of the model, the prompt and the schema. That is the appeal for some teams and the cost for others: when a CV comes back with a merged job or a wrong date, the fix is yours to find in the prompt.
Option B: send the file to a resume parser API with HTTP Request
This route replaces both nodes above with one HTTP Request node. The API reads the file itself, so the Word and scan limits of Extract From File do not apply. ResumeJSON accepts PDF, DOCX, plain text and a JPEG, PNG or WebP photo of the page, up to 20 MB, and returns the fields as typed JSON.
Configure the HTTP Request node like this. The settings names are n8n's own, as documented in October 2026.
- Method:
POST. URL:https://resumejson-resume-cv-parser-api.p.rapidapi.com/v1/parse. - Send Headers: on. Add
x-rapidapi-keywith your key from the RapidAPI listing, andx-rapidapi-hostwithresumejson-resume-cv-parser-api.p.rapidapi.com. Store the key as a credential instead of pasting it into the node. - Send Body: on. Body Content Type: Form-Data.
- Add one body parameter. Set its Parameter Type to n8n Binary File, its Name to
file, and its Input Data Field Name to the binary field from Step 1.
Run the node once. The response arrives as JSON with a resume object, and every field is reachable with an ordinary n8n expression:
{{ $json.resume.basics.full_name }}
{{ $json.resume.basics.email }}
{{ $json.resume.work[0].title }}
{{ $json.resume.skills.join(', ') }}
{{ $json.resume.total_years_experience }}The schema is fixed and documented, so the fields come back in the same shape for every CV. work and education are arrays, dates are split into parts, is_current is a boolean, and a field the CV does not state comes back as null. Our landing page states a median parse of 2.2 seconds, so a Form Trigger flow can answer the candidate while they are still on the page.
If you only want to see what comes back before you wire anything, the free parser takes one file with no signup and shows the same JSON.
The two options side by side
| Extract From File + AI extraction | HTTP Request to a parsing API | |
|---|---|---|
| Nodes in the parse step | Two, plus a model connection | One |
| PDF with a text layer | Yes | Yes |
Word (.docx) | No operation listed | Yes |
| Scanned or photographed CV | Not documented | Yes, as an image or a scanned PDF |
| Output shape | Whatever your schema says | A fixed, documented schema |
| Who fixes a bad parse | You, in the prompt and schema | The API vendor |
| What you pay for | The model calls you connect | Each parse, on the API's plan |
| Best when | You need custom fields or you already run a model you trust | You want standard resume fields from any file type with no prompt to maintain |
Neither option is free of running cost. One bills you through the model provider, the other through the API. Pick on file types and on who you want maintaining the extraction.
Step 3: route the failures instead of losing them
A real inbox sends things that are not CVs: cover letters on their own, portfolios, a blank PDF. Plan for them in the workflow.
By default the HTTP Request node "returns success only when the response returns with a 2xx code". Turn on its Never Error option so a refusal comes through as data, then add an IF node on the status code. ResumeJSON's refusals are specific, so each one can go to the right place:
| Status | Error code | What it means | What to do in n8n |
|---|---|---|---|
| 413 | too_large | The file is over 20 MB | Ask the candidate for a smaller file |
| 415 | unsupported_type | Not a PDF, DOCX, text or image | Route to a person |
| 422 | unreadable_file | The file could not be read | Route to a person, do not retry |
| 422 | not_a_resume | The document is not a CV | Mark the item and move on |
Retrying a 4xx spells the same answer again. Retry only what is transient, such as a timeout. For the AI route the equivalent check is an IF node on the fields themselves: a parse with no name and no email is a failure, and should be routed as one rather than written as an empty row.
For a backlog of files, the HTTP Request node's Batching options, Items per Batch and Batch Interval, let you pace the calls. Our bulk resume parsing guide covers sizing a large run.
Step 4: write the fields where people will use them
The last node is plain n8n. Three common destinations:
- Google Sheets or Airtable. One row per candidate, with columns mapped from the expressions above. Join
skillsinto one cell; put the latest job title and company in their own columns so the sheet sorts. The resume to Excel guide covers which columns are worth having. - A database table. Store the whole
resumeobject in a JSON column and lift the fields you search on into their own columns. That is the start of a candidate database. - Your ATS. Most ATS products take a candidate through their own API, so a second HTTP Request node maps the parsed fields onto theirs. If yours is Greenhouse, the Greenhouse API guide covers which endpoint to use.
Keep the original file alongside the row in every case. A parse is an enrichment, and somebody will want to open the real CV.
When the manual way is enough
Not every hiring flow needs a parser. Skip the parse step and just save the attachment when:
- Volume is low. A handful of applications a week is faster to read than to automate.
- A person reads every CV anyway and nothing downstream filters, sorts or searches on the fields.
- Your ATS already parses on upload. Several do, and a second parser in front of it only adds a step. Check before you build.
In those cases an n8n workflow that files each CV into a folder and posts a message to your team is still worth having, and it needs no parse step at all.
Where to go next
If you are choosing a parsing API rather than wiring n8n, the CV parser API comparison covers what each option returns and costs. If the workflow will screen candidates after parsing, automated resume screening covers the rules worth writing. And to see the JSON before you build anything, try one file in the free parser.