Automate AI Job Application — Tailored Resume & Cover Letter in 60 Seconds in n8n — Step by Step
You just found a job posting worth applying to. Now comes the part everyone hates: rewriting your resume to mirror the job description, then drafting a cover letter that doesn't read like a template.
You just found a job posting worth applying to. Now comes the part everyone hates: rewriting your resume to mirror the job description, then drafting a cover letter that doesn't read like a template. Do it well and it eats 40 minutes. Do it fast and it's generic — and generic gets filtered. This article shows you how to build an n8n workflow that takes a single job URL and returns a resume tailored to that exact role plus a cover letter that opens with something specific to the company, in about 60 seconds.
The problem: tailoring doesn't scale, and untailored doesn't convert
Recruiters and ATS filters both reward specificity. A resume that echoes the exact phrasing of the job description — "revenue operations," "GTM tooling," "Postgres and dbt" instead of your generic "data infrastructure" — ranks higher in keyword matching and reads as a closer fit to a human. A cover letter that names the company's actual product or a recent launch signals you did homework. Both take real effort per application.
So people compromise. They send the same resume to 30 roles, or they tailor two applications a week and burn out. For technical founders between things, ops leads running a search on the side, or anyone applying at volume, the math is brutal: quality per application drops exactly when you need volume. The task is mechanical enough to automate — read the posting, extract requirements, map them against a master profile, rewrite — but tedious enough that nobody does it by hand at scale. That's the sweet spot for n8n.
The solution: one URL in, two tailored documents out
The workflow is a straight pipeline. You paste a job URL (or trigger it from a form). n8n scrapes the posting, sends the job text plus your master resume to an LLM with a tailoring prompt, and returns two artifacts: a resume rewritten to foreground the skills and keywords this role asks for, and a cover letter whose first sentence references something concrete about the company. No manual editing loop — you review the output, not author it.
The key design choice is separating your master profile (everything you've ever done, stored once) from the per-job tailoring (the LLM selects and reframes from that master against each posting). You never invent experience; the model reorders, reweights, and rephrases what's already true. That keeps output honest and fast.
Step-by-step: building it in n8n
Here's the node-by-node build. It runs on any n8n instance — self-hosted or cloud.
1. Trigger — Form Trigger node. Use the Form Trigger node with a single required field named job_url (type: URL). This gives you a hosted form you can bookmark; paste a link, hit submit, done. If you'd rather fire it from a spreadsheet of postings, swap in a Schedule Trigger + Google Sheets read instead.
2. Fetch the posting — HTTP Request node. Add an HTTP Request node, method GET, URL set to {{ $json.job_url }}. Under Options, set a browser-like User-Agent header to avoid trivial blocks. For JavaScript-heavy boards (LinkedIn, Greenhouse embeds) that return empty HTML, route the URL through a scraping API — set the URL to your provider's endpoint and pass the job link as a query parameter.
3. Extract clean text — HTML node. Raw HTML is noisy. Use the HTML node in "Extract HTML Content" mode with a CSS selector targeting the job body (common ones: .job-description, [data-testid="jobDescription"], or main). Set "Return only content" so you strip tags and hand the LLM plain text. Trim to ~6,000 characters with a Set or Code node if postings run long — you don't need the legal boilerplate.
4. Load your master profile — Set node. Store your full career history once in a Set node (or pull it from a Google Docs / Notion node if you'd rather edit it outside n8n). This is the raw material: every role, metric, tool, and win. Keep it in structured form — headers per job, bullet points with numbers — so the model has clean inputs to select from.
5. Tailor — AI/LLM node (Anthropic Claude). This is the engine. Add the Message a model node using an Anthropic Chat Model credential and select a current model such as claude-sonnet-5 (fast and cheap for this, with quality headroom for the cover letter). Set the system prompt to instruct: "You are a resume tailoring assistant. Using ONLY the facts in the master profile, produce (a) a resume reordered and rephrased to match the job's required skills and exact keywords, and (b) a cover letter whose opening line references a specific detail from this company's posting. Never fabricate experience. Return valid JSON with keys resume and cover_letter." In the user message, interpolate both inputs: Job posting:\n{{ $json.job_text }}\n\nMaster profile:\n{{ $json.master_profile }}. Enable JSON output mode so the response parses cleanly downstream.
6. Parse and deliver — Code + delivery node. Add a small Code node to JSON.parse the model output into two fields. Then deliver however you work: a Google Docs "Create document" node for each artifact, a Gmail node that emails them to yourself, or a Convert to File node to generate a downloadable .md/.txt. For a full paper trail, append a row to Google Sheets with the job URL, company, timestamp, and a link to the generated docs.
Wire it Form → HTTP → HTML → Set(profile) → LLM → Code → Delivery. End to end, execution is under a minute, most of which is the LLM call.
Benefits: what this actually buys you
Volume without the quality cliff. Every application is tailored, so you can send ten a day at the quality you'd normally reserve for two. Keyword alignment for free. The model mirrors the posting's exact terminology, which is what ATS ranking rewards — you stop losing to filters before a human ever reads you. Consistency. Your master profile is the single source of truth; update one metric there and every future application inherits it. Reusability. Because it's n8n, you can fork the same pipeline for freelance proposals, grant applications, or partnership outreach — the pattern (scrape a target, tailor against a master doc) generalizes far beyond job hunting.
Common pitfalls and how to avoid them
Empty scrapes. The most frequent failure is the HTTP Request node returning a login wall or a JS shell instead of the job text. Add an IF node after the HTML extraction that checks whether job_text length is below, say, 200 characters, and routes those to a scraping-API branch or a manual-paste fallback field. Don't feed an empty posting to the LLM — it'll hallucinate a role.
Fabrication. If your prompt isn't strict, the model will "improve" your experience by inventing plausible details. Keep "use ONLY facts in the master profile" in the system prompt, and spot-check the first few outputs. A tailored resume that lies is worse than a generic honest one.
Broken JSON. LLMs occasionally wrap output in markdown fences or add a preamble. Turn on the node's JSON output mode, and in your Code node strip anything before the first { and after the last } before parsing, with a try/catch that logs the raw text so a bad run doesn't kill the workflow silently.
Over-tailoring keywords. Stuffing every phrase from the posting reads as robotic and trips some ATS spam heuristics. Instruct the model to weave keywords naturally into real accomplishments, not to list them. Rate limits and cost. If you batch dozens of URLs, add a Loop Over Items node with a small wait between iterations to stay under API rate limits and keep per-application cost visible — at Sonnet pricing this runs fractions of a cent each.
Build it once and job applications stop being a chore you avoid and become a URL you paste. The whole thing is maybe eight nodes, and the only part you maintain is your master profile.
Ja construimos isso pra voce
Nao comece do zero. O AI Job Application — Tailored Resume & Cover Letter in 60 Seconds e um workflow n8n pronto para instalar — conecta suas ferramentas em minutos, sem codigo.
Instalar por $29.0 →