Job application autofill: prefill your form from an uploaded CV
Published
Job application autofill means the applicant uploads a CV and your form fills itself: name, email, phone, location, current title, past roles and education, ready to check and submit. To build it, you parse the file the moment it is uploaded, map each parsed field to a form input, and show the applicant what was filled so they can fix anything before they send it. This article walks through that flow from start to finish for a job board, careers page or ATS, with code, the field mapping, and the edge cases that decide whether applicants trust it.
We build ResumeJSON, a resume parsing API, so read this as written by an interested party. The parse step below uses it, but the flow is the same with any parser that returns fields.
Two kinds of job application autofill
The phrase covers two different products, and it helps to know which one you are building.
- Applicant-side autofill is a browser extension or password-manager feature. The applicant stores their details once, and the extension types them into whatever form it finds on any site. It guesses which input is which from labels and names, and it works on sites that did nothing to support it.
- Form-side autofill is built by the site that owns the form. The applicant uploads a CV, the site parses it, and the site fills its own inputs. Because the site knows its own form exactly, nothing has to be guessed about which box is the phone number.
If you run the form, the second kind is yours to build, and it helps every applicant, including the ones with no extension installed. It also works well alongside extensions: a clean form with proper autocomplete attributes is the form extensions fill best.
What applicants expect from a prefilled application
People who upload a CV and then retype it field by field notice. A prefill that works earns the upload; one that half works costs trust. In practice applicants expect:
- Speed. The fields fill while they are still looking at the page. A parse that takes many seconds needs a visible progress state, or the applicant starts typing and your fill overwrites them.
- Nothing invented. A wrong value in a prefilled field is worse than an empty one, because a hurried applicant submits it. Empty fields are easy to spot. Confident wrong ones are not.
- Control. Every filled value is editable, and the applicant can see which ones came from the CV.
- A way out. If the file cannot be read, the form still works by hand, and says so.
How to build job application autofill, step by step
1. Accept the upload and parse it at once
Put the file input at the top of the form. On change, send the file to your own backend, which calls the parser. Keep your API key on the server; the browser never sees it.
// server: POST /api/prefill, receives the applicant's file
import { Hono } from 'hono'
const app = new Hono()
app.post('/api/prefill', async (c) => {
const body = await c.req.parseBody()
const file = body.file
if (!(file instanceof File)) return c.json({ error: 'no_file' }, 400)
const form = new FormData()
form.set('file', file, file.name)
const res = await fetch('https://resumejson-resume-cv-parser-api.p.rapidapi.com/v1/parse', {
method: 'POST',
headers: {
'x-rapidapi-key': process.env.RAPIDAPI_KEY,
'x-rapidapi-host': 'resumejson-resume-cv-parser-api.p.rapidapi.com'
},
body: form
})
if (!res.ok) return c.json({ error: 'parse_failed', status: res.status }, 502)
const { resume } = await res.json()
return c.json({ resume })
})ResumeJSON reads PDF, DOCX, plain text and a photo or scan of the page, so the same endpoint takes whatever applicants upload. Its landing page states a median parse of 2.2 seconds, which is short enough to run while the applicant waits instead of queueing a job.
2. Map parsed fields to form inputs
Write the mapping down once, as data. A table like this is the whole contract between the parser and your form:
| Form input | Parsed field | Notes |
|---|---|---|
| Full name | basics.full_name | Split into first and last only if your form insists |
basics.email | Validate before filling | |
| Phone | basics.phone | Written as on the CV, country code included when present |
| City / location | basics.location | Free text; map to your location picker if you have one |
| Current title | work[0].title where work[0].is_current | Leave empty when no role is current |
| Current employer | work[0].company where work[0].is_current | Same rule |
| LinkedIn / portfolio | basics.links[] | Pick by domain |
| Work history | work[] | Most recent first, dates as YYYY-MM or YYYY |
| Education | education[] | institution, degree, field_of_study |
| Years of experience | total_years_experience | Prefill a number input, still editable |
In the browser, fill only what is empty and only what the parse actually returned:
const MAP = {
full_name: (r) => r.basics.full_name,
email: (r) => r.basics.email,
phone: (r) => r.basics.phone,
location: (r) => r.basics.location,
current_title: (r) => r.work.find((w) => w.is_current)?.title ?? null,
current_company: (r) => r.work.find((w) => w.is_current)?.company ?? null,
linkedin: (r) => r.basics.links.find((l) => l.includes('linkedin.com')) ?? null
}
function prefill(form, resume) {
const filled = []
for (const [name, pick] of Object.entries(MAP)) {
const input = form.elements.namedItem(name)
const value = pick(resume)
if (!input || value == null || input.value !== '') continue
input.value = value
input.dataset.prefilled = 'true'
filled.push(name)
}
return filled
}Two rules are carrying the weight there. Never overwrite something the applicant already typed, and treat null as "leave it empty". ResumeJSON returns null for any value the CV does not state rather than guessing one, which is what makes the second rule safe: an empty field means the CV did not say, so the applicant is the right person to fill it.
3. Show what was filled, and let the applicant correct it
Mark prefilled inputs visibly, with a small "from your CV" hint beside each one, and remove the mark when the applicant edits the value. Put a one-line summary above the form: "We filled 7 fields from your CV. Please check them." Repeating sections such as work history and education work best as editable rows, one per entry, with a delete button, because a CV sometimes lists a side project as a job.
4. Handle the states that are not success
Each of these should look different to the applicant:
- Parsing: a spinner on the upload control, and the inputs still usable.
- Parsed, some fields empty: filled fields marked, empty ones left alone, and the summary line counting only what was filled.
- Could not read the file: a message saying the CV could not be read and the form works by hand, with the upload still attached if your application keeps the file.
- Service error or timeout: the same message. Never a blank form that looks as if the CV was empty.
Set a client timeout a little above the parser's typical latency, and fall back to the manual form when it expires.
5. Keep the full record on your side
The form holds a handful of fields. The parse holds the whole CV: every role with dates, skills, languages and certifications. Store the full JSON beside the application. That record is what feeds candidate matching, automated resume screening and search later, without a second parse. If you are designing that storage, how to build an ATS covers the data model.
Common traps in CV prefill
- Splitting names. "Full name" into first and last breaks on many names. Ask for one full-name field if you can.
- Current role guessed from the top entry. The first job on a CV is not always current. Use an explicit current flag, as in the mapping above, and leave the field empty when nothing is current.
- Dates in a date picker. A CV that says "2019" has no month. A picker that demands a day forces the applicant to invent one. Accept month and year, or year alone.
- Phone formats. Keep the number as written. Normalising it without knowing the country turns a correct number into a wrong one.
- Privacy. The CV is personal data. Send it only to your backend and your parser, and state that in your privacy notice. Our compliance page describes how ResumeJSON handles the file.
When manual entry is enough
Autofill is worth building when applicants arrive with a CV in hand and your form asks for more than contact details. It is not worth it when:
- your form asks only for name, email and a file, since browsers already fill the first two;
- you receive a handful of applications a month and a person reads every CV anyway;
- your applicants mostly apply from a profile they already keep on your site, where the form can be filled from that profile instead.
In those cases a well-labelled form with correct autocomplete attributes (name, email, tel) gets you most of the benefit for no integration work.
Try it on a real CV
Before you write any code, upload a CV to the free parser and look at the JSON it returns. That output is exactly what the mapping table above reads from. When you are ready to wire it into your form, the docs carry the plans, including a free tier, and the full field reference. For a deeper look at what each field holds, see extract information from a resume.