AutomationFlowsAI & RAG › Extract Data From Resume and Create PDF with Gotenberg

Extract Data From Resume and Create PDF with Gotenberg

ByOskar @workfloows on n8n.io

With this workflow you can extract data from resume documents uploaded via a Telegram bot. Workflow transform readable content of PDF resume into structured data, using AI nodes and returns PDF with formatted, plain HTML.

Event trigger★★★★★ complexityAI-powered43 nodesOpenAI ChatOutput Parser AutofixingOutput Parser StructuredTelegram TriggerTelegramHTTP RequestChain Llm
AI & RAG Trigger: Event Nodes: 43 Complexity: ★★★★★ AI nodes: yes Added:

This workflow corresponds to n8n.io template #2170 — we link there as the canonical source.

This workflow follows the Chainllm → HTTP Request recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "nodes": [
    {
      "id": "79849bb5-00a4-42e6-92c4-b06c7a20eb3e",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1580,
        340
      ],
      "parameters": {
        "model": "gpt-4-turbo-preview",
        "options": {
          "temperature": 0,
          "responseFormat": "json_object"
        }
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "85df0106-1f78-4412-8751-b84d417c8bf9",
      "name": "Convert education to HTML",
      "type": "n8n-nodes-base.code",
      "position": [
        2420,
        180
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "function convertToHTML(list) {\n    let html = '';\n\n    list.forEach((education, index) => {\n        if (index > 0) {\n            html += '<br /><br />'; // Add a new line if it's not the first item\n        }\n        html += `<b>Institution:</b> ${education.institution}<br />\n<b>Start year:</b> ${education.start_year}<br />\n<b>Degree:</b> ${education.degree}`;\n    });\n\n    return html;\n}\n\n// Assuming payload is already defined\nconst payload = $input.item.json.education;\n\nconst htmlOutput = convertToHTML(payload);\nreturn {\n    htmlOutput\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "da4fc45d-712f-4171-b72a-66b74b4d8e05",
      "name": "Auto-fixing Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserAutofixing",
      "position": [
        1820,
        340
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "225a7513-6fd4-4672-9b40-b10b00f121a7",
      "name": "OpenAI Chat Model1",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1740,
        520
      ],
      "parameters": {
        "options": {
          "temperature": 0
        }
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "0606c99d-a080-4277-b071-1bc0c93bb2e3",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1960,
        520
      ],
      "parameters": {
        "jsonSchema": "{\n  \"type\": \"object\",\n  \"properties\": {\n    \"personal_info\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"name\": { \"type\": \"string\" },\n        \"address\": { \"type\": \"string\" },\n        \"email\": { \"type\": \"string\", \"format\": \"email\" },\n        \"github\": { \"type\": \"string\"},\n        \"linkedin\": { \"type\": \"string\" }\n      }\n    },\n    \"employment_history\": {\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"position\": { \"type\": \"string\" },\n          \"company\": { \"type\": \"string\" },\n          \"duration\": { \"type\": \"string\" },\n          \"responsibilities\": {\n            \"type\": \"array\",\n            \"items\": { \"type\": \"string\" }\n          }\n        }\n      }\n    },\n    \"education\": {\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"institution\": { \"type\": \"string\" },\n          \"start_year\": { \"type\": \"integer\" },\n          \"degree\": { \"type\": \"string\" }\n        }\n      }\n    },\n    \"projects\": {\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"name\": { \"type\": \"string\" },\n          \"year\": { \"type\": \"integer\" },\n          \"description\": { \"type\": \"string\" },\n          \"technologies\": {\n            \"type\": \"array\",\n            \"items\": { \"type\": \"string\" }\n          }\n        }\n      }\n    },\n    \"volunteering\": {\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"activity\": { \"type\": \"string\" },\n          \"location\": { \"type\": \"string\" },\n          \"date\": { \"type\": \"string\" },\n          \"description\": { \"type\": \"string\" }\n        }\n      }\n    },\n    \"programming_languages\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"languages\": {\n          \"type\": \"array\",\n          \"items\": { \"type\": \"string\" }\n        },\n        \"tools\": {\n          \"type\": \"array\",\n          \"items\": { \"type\": \"string\" }\n        },\n        \"methodologies\": {\n          \"type\": \"array\",\n          \"items\": { \"type\": \"string\" }\n        }\n      }\n    },\n    \"foreign_languages\": {\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"language\": { \"type\": \"string\" },\n          \"level\": { \"type\": \"string\" }\n        }\n      }\n    }\n  }\n}\n"
      },
      "typeVersion": 1
    },
    {
      "id": "027975cd-768a-4048-858d-9060f48ab622",
      "name": "Convert employment history to HTML",
      "type": "n8n-nodes-base.code",
      "position": [
        2420,
        -20
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "function convertToHTML(list) {\n    let html = '';\n\n    list.forEach((item, index) => {\n        if (index > 0) {\n            html += '<br />'; // Add a new line if it's not the first item\n        }\n        html += `<b>Position:</b> ${item.position}\n<b>Company:</b> ${item.company}\n<br />\n<b>Duration:</b> ${item.duration}\n<br />\n<b>Responsibilities:</b>\n`;\n\n        item.responsibilities.forEach((responsibility, i) => {\n            html += `- ${responsibility}`;\n            if (i < item.responsibilities.length - 1 || index < list.length - 1) {\n                html += '<br />'; // Add new line if it's not the last responsibility in the last item\n            }\n        });\n    });\n\n    return html;\n}\n\n// Assuming payload is already defined\nconst payload = $input.item.json.employment_history;\n\nconst htmlOutput = convertToHTML(payload);\nreturn {\n    htmlOutput\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "823a241d-1c68-40a9-8f2c-f1bdfaab7603",
      "name": "Convert projects to HTML",
      "type": "n8n-nodes-base.code",
      "position": [
        2420,
        380
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "function convertToHTML(list) {\n    let html = '';\n\n    list.forEach((project, index) => {\n        if (index > 0) {\n            html += '<br />'; // Add a new line if it's not the first project\n        }\n        html += `<b>Name:</b> ${project.name}<br />\n<b>Year:</b> ${project.year}<br />\n<b>Description:</b> ${project.description}<br /><br />\n<b>Technologies:</b>\n<br />`;\n\n        project.technologies.forEach((technology, i) => {\n            html += `- ${technology}`;\n            if (i < project.technologies.length - 1 || index < list.length - 1) {\n                html += '<br />'; // Add new line if it's not the last technology in the last project\n            }\n        });\n    });\n\n    return html;\n}\n\n// Assuming payload is already defined\nconst payload = $input.item.json.projects;\n\nconst htmlOutput = convertToHTML(payload);\nreturn {\n    htmlOutput\n};\n"
      },
      "typeVersion": 2
    },
    {
      "id": "a12eb0e1-1cb9-4b83-a1ec-42dd8214f6bc",
      "name": "Convert volunteering to HTML",
      "type": "n8n-nodes-base.code",
      "position": [
        2420,
        580
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "function convertToHTML(list) {\n    let html = '';\n\n    list.forEach((event, index) => {\n        if (index > 0) {\n            html += '<br />'; // Add a new line if it's not the first volunteering event\n        }\n        html += `<b>Activity:</b> ${event.activity}<br />\n<b>Location:</b> ${event.location}<br />\n<b>Date:</b> ${event.date}<br />\n<b>Description:</b> ${event.description}<br />`;\n    });\n\n    return html;\n}\n\n// Assuming payload is already defined\nconst payload = $input.item.json.volunteering;\n\nconst htmlOutput = convertToHTML(payload);\nreturn {\n    htmlOutput\n};\n"
      },
      "typeVersion": 2
    },
    {
      "id": "70b67b80-d22d-4eea-8c97-3d2cb2b9bbfc",
      "name": "Telegram trigger",
      "type": "n8n-nodes-base.telegramTrigger",
      "position": [
        360,
        340
      ],
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "21bead1d-0665-44d5-b623-b0403c9abd6c",
      "name": "Auth",
      "type": "n8n-nodes-base.if",
      "position": [
        600,
        340
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "7ca4b4c3-e23b-4896-a823-efc85c419467",
              "operator": {
                "type": "number",
                "operation": "equals"
              },
              "leftValue": "={{ $json.message.chat.id }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "de76d6ec-3b0e-44e0-943d-55547aac2e46",
      "name": "No operation (unauthorized)",
      "type": "n8n-nodes-base.noOp",
      "position": [
        860,
        520
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "439f5e2c-be7d-486b-a1f1-13b09f77c2c8",
      "name": "Check if start message",
      "type": "n8n-nodes-base.if",
      "position": [
        860,
        220
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "1031f14f-9793-488d-bb6b-a021f943a399",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{ $json.message.text }}",
              "rightValue": "/start"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "af5f5622-c338-40c0-af72-90e124ed7ce1",
      "name": "No operation (start message)",
      "type": "n8n-nodes-base.noOp",
      "position": [
        1120,
        360
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "2efae11a-376b-44aa-ab91-9b3dea82ede0",
      "name": "Get file",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1120,
        120
      ],
      "parameters": {
        "fileId": "={{ $json.message.document.file_id }}",
        "resource": "file"
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "88fd1002-ad2c-445f-92d4-11b571db3788",
      "name": "Extract text from PDF",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        1380,
        120
      ],
      "parameters": {
        "options": {},
        "operation": "pdf"
      },
      "typeVersion": 1
    },
    {
      "id": "9dfc204b-c567-418a-93a3-9b72cf534a8c",
      "name": "Set parsed fileds",
      "type": "n8n-nodes-base.set",
      "position": [
        2040,
        120
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "314c771a-5ff2-484f-823b-0eab88f43ea3",
      "name": "Personal info",
      "type": "n8n-nodes-base.set",
      "position": [
        2420,
        -380
      ],
      "parameters": {
        "fields": {
          "values": [
            {
              "name": "personal_info",
              "stringValue": "=<b><u>Personal info</u></b>\n<br /><br />\n<b>Name:</b> {{ $json.personal_info.name }}\n<br />\n<b>Address:</b> {{ $json.personal_info.address }}\n<br />\n<b>Email:</b> {{ $json.personal_info.email }}\n<br />\n<b>GitHub:</b> {{ $json.personal_info.github }}\n<br />"
            }
          ]
        },
        "include": "none",
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "be6b32e8-6000-4235-a723-0e22828ead45",
      "name": "Technologies",
      "type": "n8n-nodes-base.set",
      "position": [
        2420,
        -200
      ],
      "parameters": {
        "fields": {
          "values": [
            {
              "name": "technologies",
              "stringValue": "=<b><u>Technologies</u></b>\n<br /><br />\n<b>Programming languages:</b> {{ $json.programming_languages.languages.join(', ') }}\n<br />\n<b>Tools:</b> {{ $json.programming_languages.tools.join(', ') }}\n<br />\n<b>Methodologies:</b> {{ $json.programming_languages.methodologies.join(', ') }}\n<br />"
            }
          ]
        },
        "include": "none",
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "ab726d61-84b8-4af7-a195-33e1add89153",
      "name": "Employment history",
      "type": "n8n-nodes-base.set",
      "position": [
        2640,
        -20
      ],
      "parameters": {
        "fields": {
          "values": [
            {
              "name": "employment_history",
              "stringValue": "=<b><u>Employment history</u></b>\n<br /><br />\n{{ $json[\"htmlOutput\"] }}"
            }
          ]
        },
        "include": "none",
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "692f9555-6102-4d3c-b0a1-868e27e3c343",
      "name": "Education",
      "type": "n8n-nodes-base.set",
      "position": [
        2640,
        180
      ],
      "parameters": {
        "fields": {
          "values": [
            {
              "name": "education",
              "stringValue": "=<b><u>Education</u></b>\n<br /><br />\n{{ $json[\"htmlOutput\"] }}"
            }
          ]
        },
        "include": "none",
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "258728f2-1f03-4786-8197-feb9f1bc4dfe",
      "name": "Projects",
      "type": "n8n-nodes-base.set",
      "position": [
        2640,
        380
      ],
      "parameters": {
        "fields": {
          "values": [
            {
              "name": "projects",
              "stringValue": "=<b><u>Projects</u></b>\n<br /><br />\n{{ $json[\"htmlOutput\"] }}"
            }
          ]
        },
        "include": "none",
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "3c819ce4-235a-4b12-a396-d33dca9f80da",
      "name": "Volunteering",
      "type": "n8n-nodes-base.set",
      "position": [
        2640,
        580
      ],
      "parameters": {
        "fields": {
          "values": [
            {
              "name": "volunteering",
              "stringValue": "=<b><u>Volunteering</u></b>\n<br /><br />\n{{ $json[\"htmlOutput\"] }}"
            }
          ]
        },
        "include": "none",
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "41bd7506-7330-4c25-8b43-aa3c836736fc",
      "name": "Merge education and employment history",
      "type": "n8n-nodes-base.merge",
      "position": [
        2880,
        100
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combinationMode": "multiplex"
      },
      "typeVersion": 2.1
    },
    {
      "id": "d788da36-360b-4009-82ad-2f206fad8e53",
      "name": "Merge projects and volunteering",
      "type": "n8n-nodes-base.merge",
      "position": [
        2880,
        500
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combinationMode": "multiplex"
      },
      "typeVersion": 2.1
    },
    {
      "id": "57c20e19-3d84-41c0-a415-1d55cb031da1",
      "name": "Merge personal info and technologies",
      "type": "n8n-nodes-base.merge",
      "position": [
        3140,
        -160
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combinationMode": "multiplex"
      },
      "typeVersion": 2.1
    },
    {
      "id": "f12be010-8375-4ff7-ba8e-9c2c870f648b",
      "name": "Merge all",
      "type": "n8n-nodes-base.merge",
      "position": [
        3400,
        200
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combinationMode": "multiplex"
      },
      "typeVersion": 2.1
    },
    {
      "id": "d6428167-2c75-42a5-a905-7590ff1d6a25",
      "name": "Set final data",
      "type": "n8n-nodes-base.set",
      "position": [
        3620,
        200
      ],
      "parameters": {
        "fields": {
          "values": [
            {
              "name": "output",
              "stringValue": "={{ $json.personal_info }}\n<br /><br />\n{{ $json.employment_history }}\n<br /><br />\n{{ $json.education }}\n<br /><br />\n{{ $json.projects }}\n<br /><br />\n{{ $json.volunteering }}\n<br /><br />\n{{ $json.technologies }}"
            }
          ]
        },
        "include": "none",
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "9ea13c62-2e09-4b37-b889-66edaef1fcf1",
      "name": "Convert raw to base64",
      "type": "n8n-nodes-base.code",
      "position": [
        3840,
        200
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const encoded = Buffer.from($json.output).toString('base64');\n\nreturn { encoded };"
      },
      "typeVersion": 2
    },
    {
      "id": "c4474fa1-b1b5-432f-b30e-100201c9ec7c",
      "name": "Convert to HTML",
      "type": "n8n-nodes-base.convertToFile",
      "position": [
        4060,
        200
      ],
      "parameters": {
        "options": {
          "fileName": "index.html",
          "mimeType": "text/html"
        },
        "operation": "toBinary",
        "sourceProperty": "encoded"
      },
      "typeVersion": 1.1
    },
    {
      "id": "3c4d2010-1bdc-4f01-bb1a-bd0128017787",
      "name": "Generate plain PDF doc",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        4340,
        200
      ],
      "parameters": {
        "url": "http://gotenberg:3000/forms/chromium/convert/html",
        "method": "POST",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        },
        "sendBody": true,
        "contentType": "multipart-form-data",
        "bodyParameters": {
          "parameters": [
            {
              "name": "files",
              "parameterType": "formBinaryData",
              "inputDataFieldName": "data"
            }
          ]
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "2b3cd55f-21a3-4c14-905f-82b158aa3fd0",
      "name": "Send PDF to the user",
      "type": "n8n-nodes-base.telegram",
      "position": [
        4640,
        200
      ],
      "parameters": {
        "chatId": "={{ $('Telegram trigger').item.json[\"message\"][\"chat\"][\"id\"] }}",
        "operation": "sendDocument",
        "binaryData": true,
        "additionalFields": {
          "fileName": "={{ $('Set parsed fileds').item.json[\"personal_info\"][\"name\"].toLowerCase().replace(' ', '-') }}.pdf"
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "54fe1d2d-eb9d-4fe1-883f-1826e27ac873",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        540,
        180
      ],
      "parameters": {
        "width": 226.21234567901217,
        "height": 312.917333333334,
        "content": "### Add chat ID\nRemember to set your actual ID to trigger automation from Telegram."
      },
      "typeVersion": 1
    },
    {
      "id": "b193a904-260b-4d45-8a66-e3cb46fc7ce4",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        800,
        83.43940740740783
      ],
      "parameters": {
        "width": 229.64938271604922,
        "height": 293.54824691358016,
        "content": "### Ignore start message\nWorkflow ignores initial`/start` message sent to the bot."
      },
      "typeVersion": 1
    },
    {
      "id": "d5c95d8f-b699-4a8e-9460-a4f5856b5e6f",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1066,
        -20
      ],
      "parameters": {
        "width": 211.00246913580224,
        "height": 302.41975308642,
        "content": "### Download resume file\nBased on file ID, node performs downloading of the file uploaded by user."
      },
      "typeVersion": 1
    },
    {
      "id": "2de0751d-8e11-457e-8c38-a6dcca59190c",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1320,
        -20
      ],
      "parameters": {
        "width": 217.87654320987633,
        "height": 302.41975308642,
        "content": "### Extract text from PDF\nNode extracts readable text form PDF."
      },
      "typeVersion": 1
    },
    {
      "id": "4b9ccab8-ff6c-408f-93fe-f148034860a0",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1580,
        -20
      ],
      "parameters": {
        "width": 410.9479506172837,
        "height": 302.41975308642,
        "content": "### Parse resume data\nCreate structured data from text extracted from resume. Chain uses OpenAI `gpt-4-turbo-preview` model and JSON response mode. **Adjust JSON schema in output parser to your needs.**"
      },
      "typeVersion": 1
    },
    {
      "id": "bfb1d382-90fa-4bff-8c38-04e53bcf5f58",
      "name": "Parse resume data",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        1660,
        120
      ],
      "parameters": {
        "prompt": "={{ $json.text }}",
        "messages": {
          "messageValues": [
            {
              "message": "Your task is to extract all necessary data such as first name, last name, experience, known technologies etc. from the provided resume text and return in well-unified JSON format. Do not make things up."
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "7e8eb10a-f21c-4a9c-90b1-b71537b78356",
      "name": "Merge other data",
      "type": "n8n-nodes-base.merge",
      "position": [
        3140,
        340
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combinationMode": "multiplex"
      },
      "typeVersion": 2.1
    },
    {
      "id": "7c4398de-7b4d-4095-b38f-eaf099d2991b",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2340,
        -491.4074074074074
      ],
      "parameters": {
        "width": 1196.8442469135782,
        "height": 1260.345679012346,
        "content": "### Format HTML\nFormat HTML for each resume section (employment history, projects etc.)."
      },
      "typeVersion": 1
    },
    {
      "id": "9de2f504-6ff0-4b00-8e0d-436c789b4e23",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3580,
        40
      ],
      "parameters": {
        "width": 638.6516543209876,
        "height": 322.5837037037037,
        "content": "### Create HTML file\nFrom formatted output create `index.html` file in order to run PDF conversion."
      },
      "typeVersion": 1
    },
    {
      "id": "11abdff5-377e-490d-9136-15c24ff6a05e",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4260,
        39.83604938271645
      ],
      "parameters": {
        "color": 3,
        "width": 262.0096790123454,
        "height": 322.5837037037035,
        "content": "### Convert file to PDF\nForm `index.html` create PDF using [Gotenberg](https://gotenberg.dev/). If you're not familiar with this software, feel free to check out [my tutorial on YouTube](https://youtu.be/bo15xdjXf1Y?si=hFZMTfjzfSOLOLPK)."
      },
      "typeVersion": 1
    },
    {
      "id": "73fb81d0-5218-4311-aaec-7fa259d8cbd3",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4560,
        40
      ],
      "parameters": {
        "width": 262.0096790123454,
        "height": 322.5837037037035,
        "content": "### Send PDF file to user\nDeliver converted PDF to Telegram user (based on chat ID)."
      },
      "typeVersion": 1
    },
    {
      "id": "bb5fa375-4cc9-4559-a014-7b618d6c5f32",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -280,
        128
      ],
      "parameters": {
        "width": 432.69769500990674,
        "height": 364.2150828344463,
        "content": "## \u26a0\ufe0f Note\n\nThis is *resume extractor* workflow that I had a pleasure to present during [n8n community hangout](https://youtu.be/eZacuxrhCuo?si=KkJQrgQuvLxj-6FM&t=1701\n) on March 7, 2024.\n\n1. Remember to add your credentials and configure nodes.\n2. This node requires installed [Gotenberg](https://gotenberg.dev/) for PDF generation. If you're not familiar with this software, feel free to check out [my tutorial on YouTube](https://youtu.be/bo15xdjXf1Y?si=hFZMTfjzfSOLOLPK). If you don't want to self-host Gotenberg, you use other PDF generation provider (PDFMonkey, ApiTemplate or similar).\n3. If you like this workflow, please subscribe to [my YouTube channel](https://www.youtube.com/@workfloows) and/or [my newsletter](https://workfloows.com/).\n\n**Thank you for your support!**"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Auth": {
      "main": [
        [
          {
            "node": "Check if start message",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No operation (unauthorized)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get file": {
      "main": [
        [
          {
            "node": "Extract text from PDF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Projects": {
      "main": [
        [
          {
            "node": "Merge projects and volunteering",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Education": {
      "main": [
        [
          {
            "node": "Merge education and employment history",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge all": {
      "main": [
        [
          {
            "node": "Set final data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Technologies": {
      "main": [
        [
          {
            "node": "Merge personal info and technologies",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Volunteering": {
      "main": [
        [
          {
            "node": "Merge projects and volunteering",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Personal info": {
      "main": [
        [
          {
            "node": "Merge personal info and technologies",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set final data": {
      "main": [
        [
          {
            "node": "Convert raw to base64",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert to HTML": {
      "main": [
        [
          {
            "node": "Generate plain PDF doc",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge other data": {
      "main": [
        [
          {
            "node": "Merge all",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Telegram trigger": {
      "main": [
        [
          {
            "node": "Auth",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Parse resume data",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Parse resume data": {
      "main": [
        [
          {
            "node": "Set parsed fileds",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set parsed fileds": {
      "main": [
        [
          {
            "node": "Convert employment history to HTML",
            "type": "main",
            "index": 0
          },
          {
            "node": "Convert education to HTML",
            "type": "main",
            "index": 0
          },
          {
            "node": "Convert projects to HTML",
            "type": "main",
            "index": 0
          },
          {
            "node": "Personal info",
            "type": "main",
            "index": 0
          },
          {
            "node": "Convert volunteering to HTML",
            "type": "main",
            "index": 0
          },
          {
            "node": "Technologies",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Employment history": {
      "main": [
        [
          {
            "node": "Merge education and employment history",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "Auto-fixing Output Parser",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Convert raw to base64": {
      "main": [
        [
          {
            "node": "Convert to HTML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract text from PDF": {
      "main": [
        [
          {
            "node": "Parse resume data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if start message": {
      "main": [
        [
          {
            "node": "Get file",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No operation (start message)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate plain PDF doc": {
      "main": [
        [
          {
            "node": "Send PDF to the user",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert projects to HTML": {
      "main": [
        [
          {
            "node": "Projects",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Auto-fixing Output Parser",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Auto-fixing Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Parse resume data",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Convert education to HTML": {
      "main": [
        [
          {
            "node": "Education",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert volunteering to HTML": {
      "main": [
        [
          {
            "node": "Volunteering",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge projects and volunteering": {
      "main": [
        [
          {
            "node": "Merge other data",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Convert employment history to HTML": {
      "main": [
        [
          {
            "node": "Employment history",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge personal info and technologies": {
      "main": [
        [
          {
            "node": "Merge all",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge education and employment history": {
      "main": [
        [
          {
            "node": "Merge other data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

With this workflow you can extract data from resume documents uploaded via a Telegram bot. Workflow transform readable content of PDF resume into structured data, using AI nodes and returns PDF with formatted, plain HTML.

Source: https://n8n.io/workflows/2170/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

This workflow contains community nodes that are only compatible with the self-hosted version of n8n.

Output Parser Structured, Telegram, N8N Nodes Tesseractjs +14
AI & RAG

This workflow is for users who want to turn Telegram into a personal AI-powered assistant capable of handling everyday tasks through natural language. It's ideal for solo founders, operators, or profe

Memory Buffer Window, Tool Workflow, Tool Think +9
AI & RAG

This n8n template demonstrates how to create authentic-looking User Generated Content (UGC) advertisements using AI image generation, voice synthesis, and lip-sync technology. The workflow transforms

Chain Llm, Output Parser Structured, Agent +5
AI & RAG

📌 How it works

Telegram Trigger, Telegram, OpenAI +5
AI & RAG

++HOW IT WORKS:++ This workflow automates the processing of invoices sent via Telegram. It extracts the data using LlamaIndex OCR, logs it in Google Sheets, and optionally pushes the structured data t

Chain Llm, OpenAI Chat, Telegram Trigger +4