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 →
{
"id": "2Zpk5qEVwjbHHnXk",
"name": "LinkedIn Job Search \u2014 Auto 5min",
"active": true,
"isArchived": false,
"versionId": "3217c159-f81e-434c-8aa3-9551d646dd9c",
"description": "Searches LinkedIn jobs every 5min, deduplicates via Data Table, filters by allowed locations, and sends grouped notifications to Telegram.",
"settings": {
"executionOrder": "v1",
"availableInMCP": true,
"binaryMode": "separate",
"timeSavedMode": "fixed",
"timezone": "Europe/Paris",
"saveDataErrorExecution": "all",
"saveDataSuccessExecution": "all",
"saveExecutionProgress": true,
"callerPolicy": "workflowsFromSameOwner",
"timeSavedPerExecution": 5,
"saveManualExecutions": true
},
"nodes": [
{
"id": "92749f11-ad32-46dc-81ea-e668c45ac4f0",
"name": "Every 5 Minutes",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.3,
"position": [
192,
304
],
"parameters": {
"rule": {
"interval": [
{
"field": "minutes",
"minutesInterval": 5
}
]
}
}
},
{
"id": "2167bf68-fe17-4659-a553-e2dffdd874b8",
"name": "Config Filters",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
432,
304
],
"parameters": {
"jsCode": "const config = {\n keywords: [\n \"Developpeur fullstack\",\n \"developpeur front end\",\n \"integrateur IA\",\n \"vibecoder\"\n ],\n remoteLocations: [\"France\", \"Luxembourg\", \"Suisse\", \"Belgique\"],\n hybridLocations: [\"Dijon\", \"Ahuy\", \"Fontaine-les-dijon\", \"Luxembourg\"],\n officeLocations: [\"Dijon\", \"Ahuy\", \"Fontaine-les-dijon\", \"Luxembourg\"],\n dateSincePosted: \"24hr\",\n jobType: \"full time\",\n salary: \"60000\",\n experienceLevel: \"\",\n sortBy: \"recent\",\n limit: 0,\n page: 0,\n has_verification: false,\n under_10_applicants: true,\n host: \"www.linkedin.com\",\n allowedLocations: [\n \"France\",\n \"Luxembourg\",\n \"Suisse\",\n \"Belgique\",\n \"Belgium\",\n \"Dijon\",\n \"Ahuy\",\n \"Fontaine-les-dijon\",\n \"Fontaine-l\u00e8s-Dijon\",\n \"Bourgogne\",\n \"Burgundy\",\n \"C\u00f4te-d\",\n \"Bruxelles\",\n \"Brussels\",\n \"Gen\u00e8ve\",\n \"Geneva\",\n \"Zurich\",\n \"Z\u00fcrich\",\n \"Bern\",\n \"Basel\",\n \"Lausanne\",\n \"Paris\",\n \"Lyon\",\n \"Marseille\",\n \"Toulouse\",\n \"Nantes\",\n \"Strasbourg\",\n \"Lille\",\n \"Bordeaux\",\n \"Nice\",\n \"Rennes\",\n \"Grenoble\",\n \"Montpellier\",\n \"Metz\",\n \"Nancy\",\n \"Besan\u00e7on\",\n \"Reims\",\n \"Li\u00e8ge\",\n \"Namur\",\n \"Antwerpen\",\n \"Gent\",\n \"Charleroi\",\n \"Kirchberg\",\n \"Esch\",\n \"Capellen\",\n \"Pontpierre\",\n \"Koerich\",\n \"Lacaussade\",\n \"Niort\",\n \"Fully\",\n \"Valais\"\n ]\n};\nreturn [{ json: config }];"
}
},
{
"id": "70ef0d25-07fa-4a14-aa5b-a1e468f1bbd1",
"name": "LinkedIn Job Search",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
656,
304
],
"parameters": {
"jsCode": "const config = $input.first().json;\n\nconst DM = { \"past month\": \"r2592000\", \"past week\": \"r604800\", \"24hr\": \"r86400\" };\nconst JM = { \"full time\": \"F\", \"part time\": \"P\", \"contract\": \"C\", \"temporary\": \"T\", \"volunteer\": \"V\", \"internship\": \"I\" };\nconst RM = { \"on site\": \"1\", \"remote\": \"2\", \"hybrid\": \"3\" };\nconst EM = { \"internship\": \"1\", \"entry level\": \"2\", \"associate\": \"3\", \"senior\": \"4\", \"director\": \"5\", \"executive\": \"6\" };\nconst SM = { \"40000\": \"1\", \"60000\": \"2\", \"80000\": \"3\", \"100000\": \"4\", \"120000\": \"5\" };\n\nfunction ep(obj) {\n return Object.entries(obj).filter(([,v]) => v !== \"\" && v != null).map(([k,v]) => encodeURIComponent(k) + \"=\" + encodeURIComponent(v)).join(\"&\");\n}\n\nfunction bUrl(kw, loc, rf) {\n const p = {};\n p.keywords = kw;\n p.location = loc;\n if (config.dateSincePosted) p.f_TPR = DM[config.dateSincePosted] || \"\";\n if (config.jobType) p.f_JT = JM[config.jobType] || \"\";\n p.f_WT = RM[rf] || \"\";\n if (config.salary) p.f_SB2 = SM[config.salary] || \"\";\n if (config.experienceLevel) p.f_E = EM[config.experienceLevel] || \"\";\n p.sortBy = config.sortBy === \"recent\" ? \"DD\" : \"R\";\n p.start = String((config.page || 0) * 25);\n if (config.under_10_applicants) p.f_EA = \"true\";\n if (config.has_verification) p.f_VJ = \"true\";\n return \"https://\" + (config.host || \"www.linkedin.com\") + \"/jobs-guest/jobs/api/seeMoreJobPostings/search?\" + ep(p);\n}\n\nconst queries = [];\nfor (const kw of config.keywords) {\n for (const loc of config.remoteLocations) {\n queries.push({ keyword: kw, location: loc, remoteFilter: \"remote\", url: bUrl(kw, loc, \"remote\") });\n }\n for (const loc of config.hybridLocations) {\n queries.push({ keyword: kw, location: loc, remoteFilter: \"hybrid\", url: bUrl(kw, loc, \"hybrid\") });\n }\n for (const loc of config.officeLocations) {\n queries.push({ keyword: kw, location: loc, remoteFilter: \"on site\", url: bUrl(kw, loc, \"on site\") });\n }\n}\n\nconst UAs = [\n \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36\",\n \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36\",\n \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36\"\n];\nfunction rUA() { return UAs[Math.floor(Math.random() * UAs.length)]; }\n\nfunction parse(html) {\n const jobs = [];\n const parts = html.split(/<\\/li>/gi);\n for (const card of parts) {\n const t = card.match(/base-search-card__title[^>]*>\\s*([^<]+)/i);\n const co = card.match(/hidden-nested-link[^>]*>\\s*([^<]+)/i);\n const lo = card.match(/job-search-card__location[^>]*>\\s*([^<]+)/i);\n const u = card.match(/href=\"(https:\\/\\/[^\"]*linkedin\\.com\\/jobs\\/view\\/[^\"]+)\"/i);\n const d = card.match(/<time[^>]*datetime=\"([^\"]+)\"/i);\n const a = card.match(/<time[^>]*>\\s*([^<]+)/i);\n const s = card.match(/job-search-card__salary-info[^>]*>\\s*([^<]+)/i);\n const pos = t ? t[1].trim() : \"\";\n const comp = co ? co[1].trim() : \"\";\n if (!pos || !comp) continue;\n jobs.push({ position: pos, company: comp, location: lo ? lo[1].trim() : \"\", date: d ? d[1].trim() : \"\", salary: s ? s[1].trim() : \"\", jobUrl: u ? u[1].split(\"?\")[0].trim() : \"\", agoTime: a ? a[1].trim() : \"\" });\n }\n return jobs;\n}\n\nconst sl = ms => new Promise(r => setTimeout(r, ms));\nconst allJobs = [];\nlet err = 0;\n\nfor (const q of queries) {\n try {\n const r = await this.helpers.httpRequest({\n method: \"GET\", url: q.url,\n headers: { \"User-Agent\": rUA(), \"Accept\": \"text/html\", \"Accept-Language\": \"fr-FR,fr;q=0.9\", \"Referer\": \"https://www.linkedin.com/jobs/search/\" },\n returnFullResponse: true, ignoreHttpStatusErrors: true\n });\n if (r.statusCode === 429) { err++; await sl(Math.pow(2, err) * 1000); continue; }\n if (r.statusCode === 200 && r.body) {\n const jobs = parse(typeof r.body === \"string\" ? r.body : \"\");\n for (const j of jobs) { j.searchKeyword = q.keyword; j.searchLocation = q.location; j.searchRemoteFilter = q.remoteFilter; }\n allJobs.push(...jobs);\n err = 0;\n }\n } catch (e) { err++; if (err >= 3) break; }\n await sl(2000 + Math.random() * 1000);\n}\n\nconst seen = new Set();\nconst unique = [];\nfor (const j of allJobs) {\n if (j.jobUrl && !seen.has(j.jobUrl)) { seen.add(j.jobUrl); unique.push(j); }\n}\n\nconst allowed = (config.allowedLocations || []).map(s => s.toLowerCase());\nconst filtered = unique.filter(j => {\n if (!j.location) return false;\n const loc = j.location.toLowerCase();\n return allowed.some(a => loc.includes(a));\n});\n\nreturn filtered.map(j => ({ json: j }));"
}
},
{
"id": "0459a9ca-598c-4e72-8a2c-52c128fe8b32",
"name": "Check Duplicates",
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
928,
176
],
"parameters": {
"operation": "rowNotExists",
"dataTableId": {
"__rl": true,
"mode": "id",
"value": "oF0q52yUm9Da7t0D"
},
"matchType": "allConditions",
"filters": {
"conditions": [
{
"keyName": "jobUrl",
"keyValue": "={{ $json.jobUrl }}"
}
]
}
}
},
{
"id": "eccf5433-2880-4e1e-bb93-afdc48f3f7d4",
"name": "Group by Type",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1328,
304
],
"parameters": {
"jsCode": "const items = $input.all();\nconst groups = { remote: [], hybrid: [], \"on site\": [] };\nfor (const item of items) {\n const rf = item.json.searchRemoteFilter;\n if (groups[rf]) groups[rf].push(item.json);\n}\nconst results = [];\nfor (const [type, jobs] of Object.entries(groups)) {\n if (jobs.length === 0) continue;\n const label = type === \"remote\" ? \"REMOTE\" : type === \"hybrid\" ? \"HYBRIDE\" : \"OFFICE\";\n let msg = \"<b>\" + label + \" \u2014 \" + jobs.length + \" nouvelle(s) offre(s)</b>\\n\\n\";\n for (const j of jobs) {\n msg += \"<b>\" + j.position + \"</b>\\n\";\n msg += j.company + \" | \" + j.location + \"\\n\";\n if (j.salary) msg += j.salary + \"\\n\";\n msg += j.agoTime + \" | \" + j.searchKeyword + \"\\n\";\n if (j.jobUrl) msg += '<a href=\"' + j.jobUrl + '\">Voir sur LinkedIn</a>\\n';\n msg += \"\\n\";\n }\n results.push({ json: { chatId: \"387442030\", message: msg, jobCount: jobs.length } });\n}\nif (results.length === 0) {\n results.push({ json: { chatId: \"387442030\", message: \"\", jobCount: 0 } });\n}\nreturn results;"
}
},
{
"id": "a0d30d12-1074-4412-a1dd-9901c23ee67f",
"name": "Has New Jobs",
"type": "n8n-nodes-base.if",
"typeVersion": 2.3,
"position": [
1552,
304
],
"parameters": {
"conditions": {
"conditions": [
{
"leftValue": "={{ $json.jobCount }}",
"operator": {
"type": "number",
"operation": "gt"
},
"rightValue": 0
}
]
},
"options": {}
}
},
{
"id": "01c5209b-fb66-43a8-b56b-2d3b019de10a",
"name": "Send to Telegram",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.2,
"position": [
1808,
192
],
"parameters": {
"chatId": "={{ $json.chatId }}",
"text": "={{ $json.message }}",
"additionalFields": {
"appendAttribution": false,
"disable_web_page_preview": false,
"parse_mode": "HTML"
}
}
},
{
"id": "69af2c31-805e-4cd3-862c-c0eff8505650",
"name": "Save New Jobs",
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
1344,
480
],
"parameters": {
"dataTableId": {
"__rl": true,
"mode": "id",
"value": "oF0q52yUm9Da7t0D"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"jobUrl": "={{ $json.jobUrl }}",
"position": "={{ $json.position }}",
"company": "={{ $json.company }}",
"addedAt": "={{ $now.toISO() }}"
}
},
"options": {}
}
}
],
"connections": {
"Every 5 Minutes": {
"main": [
[
{
"node": "Config Filters",
"type": "main",
"index": 0
}
]
]
},
"Config Filters": {
"main": [
[
{
"node": "LinkedIn Job Search",
"type": "main",
"index": 0
}
]
]
},
"LinkedIn Job Search": {
"main": [
[
{
"node": "Check Duplicates",
"type": "main",
"index": 0
}
]
]
},
"Check Duplicates": {
"main": [
[
{
"node": "Group by Type",
"type": "main",
"index": 0
},
{
"node": "Save New Jobs",
"type": "main",
"index": 0
}
]
]
},
"Group by Type": {
"main": [
[
{
"node": "Has New Jobs",
"type": "main",
"index": 0
}
]
]
},
"Has New Jobs": {
"main": [
[
{
"node": "Send to Telegram",
"type": "main",
"index": 0
}
]
]
}
},
"meta": {
"aiBuilderAssisted": true
},
"tags": []
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
LinkedIn Job Search — Auto 5min. Uses dataTable, telegram. Scheduled trigger; 8 nodes.
Source: https://github.com/SergeMiro/smiro.dev/blob/main/n8n/job_autosearch/docs/initial-linkedin-only-5min-backup.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This n8n workflow is designed for content curators, digital marketers, and social media managers who want to automate the process of discovering, translating, and publishing news content from multiple
Social Media AI Agent - Telegram. Uses httpRequest, airtable, linkedIn, twitter. Scheduled trigger; 26 nodes.
Save time - Eliminate manual LinkedIn posting and content scheduling tasks Stay consistent - Automated daily posting keeps your LinkedIn profile active and engaging Keep control - Preview every post b
> 📊 See real sample data this workflow collects: > View Sample Google Sheet →
This workflow is perfect for content creators, social media managers, and businesses who want to schedule and automatically post videos 📹 to multiple platforms (Instagram, LinkedIn, TikTok) without ma