AutomationFlowsSocial Media › Linkedin Job Search — Auto 5min

Linkedin Job Search — Auto 5min

LinkedIn Job Search — Auto 5min. Uses dataTable, telegram. Scheduled trigger; 8 nodes.

Cron / scheduled trigger★★★★☆ complexity8 nodesData TableTelegram
Social Media Trigger: Cron / scheduled Nodes: 8 Complexity: ★★★★☆ Added:

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
{
  "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": []
}
Pro

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 →

More Social Media workflows → · Browse all categories →

Related workflows

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

Social Media

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

Edit Image, Facebook Graph Api, WordPress +9
Social Media

Social Media AI Agent - Telegram. Uses httpRequest, airtable, linkedIn, twitter. Scheduled trigger; 26 nodes.

HTTP Request, Airtable, LinkedIn +2
Social Media

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

HTTP Request, Telegram, Google Sheets +2
Social Media

&gt; 📊 See real sample data this workflow collects: &gt; View Sample Google Sheet →

Google Sheets, Data Table, @Apify/N8N Nodes Apify
Social Media

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

Google Sheets, Telegram, N8N Nodes Upload Post