AutomationFlowsEmail & Gmail › Daily LinkedIn Job Alerts via Apify & Gmail

Daily LinkedIn Job Alerts via Apify & Gmail

Original n8n title: Daily Linkedin Job Alerts with Apify Scraper, Google Sheets & Gmail

ByRobin Geuens @robingeuens on n8n.io

Every day, this workflow scrapes LinkedIn jobs based on your keywords, saves them in a Google Sheet, and sends them by email. The workflow runs every day at noon. The Apify node sends a request to a LinkedIn scraper actor on Apify, which scrapes and returns the data. The code…

Cron / scheduled trigger★★★★☆ complexity12 nodesGmail@Apify/N8N Nodes ApifyGoogle Sheets
Email & Gmail Trigger: Cron / scheduled Nodes: 12 Complexity: ★★★★☆ Added:

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

This workflow follows the Apifyn8N Nodes Apify → Google Sheets 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
{
  "id": "FXH3iheVDhMKnGyN",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Scrape LinkedIn Jobs with Apify, save to Google Sheets & email via Gmail",
  "tags": [],
  "nodes": [
    {
      "id": "02a34e91-d6e6-4c2b-a5d9-cc93caa39d59",
      "name": "Send a message",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1056,
        384
      ],
      "parameters": {
        "message": "=<h2> Job summary for {{ $now.format('dd MMMM yyyy') }}</h2>\n\n\n{{ $json.data.map(item => item.html).join('<br/>') }}",
        "options": {
          "appendAttribution": false
        },
        "subject": "=Job summary for {{ $now.format('dd MMMM yyyy')}}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "bf2ff9e4-cc09-47ef-97e5-ef5d949c3825",
      "name": "Get LinkedIn jobs",
      "type": "@apify/n8n-nodes-apify.apify",
      "position": [
        192,
        384
      ],
      "parameters": {
        "actorId": {
          "__rl": true,
          "mode": "list",
          "value": "KE649tixwpoRnZtJJ",
          "cachedResultUrl": "https://console.apify.com/actors/KE649tixwpoRnZtJJ/input",
          "cachedResultName": "LinkedIn Jobs Scraper - No Cookies (apimaestro/linkedin-jobs-scraper-api)"
        },
        "operation": "Run actor and get dataset",
        "customBody": "{\n    \"date_posted\": \"day\",\n    \"keywords\": \"SEO manager\",\n    \"limit\": 10,\n    \"location\": \"United States\",\n    \"sort\": \"recent\"\n}"
      },
      "credentials": {
        "apifyApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "b1d89bb8-2fe9-4cbf-94f6-4a9c989be91f",
      "name": "Set job data & HTML",
      "type": "n8n-nodes-base.code",
      "position": [
        480,
        384
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const company = $input.item.json.company;\nconst job_title = $input.item.json.job_title;\nconst job_url = $input.item.json.job_url;\nconst location = $input.item.json.location;\nconst work_type = $input.item.json.work_type ? $input.item.json.work_type : 'Not specified';\nconst salary = $input.item.json.salary ? $input.item.json.salary : \"Not specified\";\n\nconst html_item = `<b><a href=\"${job_url}\">${job_title} - ${company}</a></b><br />Salary: ${salary} <br />Location: ${location} <br />Remote or on-site: ${work_type} <br />`;\n\nreturn {\n  json: {\n    html: html_item,\n  },\n};\n"
      },
      "typeVersion": 2
    },
    {
      "id": "16e9e8d9-9b4c-40ad-b005-a13dd0536d3d",
      "name": "Combine items into one list",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        768,
        384
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "664e0abe-6144-414c-af24-ead89d6461ba",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        112,
        -224
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "height": 784,
        "content": "## Get LinkedIn jobs\nUse Apify to scrape LinkedIn jobs. This workflow uses the [`LinkedIn Jobs Scraper - No Cookies`](https://apify.com/apimaestro/linkedin-jobs-scraper-api`) actor on Apify.\n\nNote that you can use a HTTP node instead of the Apify community node."
      },
      "typeVersion": 1
    },
    {
      "id": "2be1eebd-c624-47b5-b1b6-4882331165ae",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        400,
        -224
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "height": 784,
        "content": "## Set job data and HTML and add to Google Sheets\nAdd the jobs to a Google Sheet so we can reference them at a later date\n\nAt the same time, we use a code node to set the data we want to use in the email. We format the data using HTML so it looks nice in our email."
      },
      "typeVersion": 1
    },
    {
      "id": "1e219262-b334-4a0e-abac-54cb03ff2740",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        688,
        -224
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "height": 784,
        "content": "## Combine items into one list\nWe combine all the different items into one big list"
      },
      "typeVersion": 1
    },
    {
      "id": "8f2413c7-0d59-4b9b-be72-e061a5966861",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        976,
        -224
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "height": 784,
        "content": "## Send email\nWe send an email with a list of all the jobs titles, salaries, and more"
      },
      "typeVersion": 1
    },
    {
      "id": "ba3571ef-7865-4e05-a246-622ce08e0e5d",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -176,
        -224
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "height": 784,
        "content": "## Scheduled trigger\nRun this workflow every day at noon"
      },
      "typeVersion": 1
    },
    {
      "id": "05d9eab8-5ddf-4bbe-af11-65ec78418f25",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -784,
        -224
      ],
      "parameters": {
        "color": 7,
        "width": 576,
        "height": 1200,
        "content": "## Overview\nEvery day, this workflow scrapes LinkedIn jobs based on your keywords, saves them in a Google Sheet, and sends them by email.\n\n## How it works\n- The workflow runs every day at noon.\n- The Apify node sends a request to a LinkedIn scraper actor on Apify, which scrapes and returns the data.\n- The code node formats the data we want and builds the HTML needed to make the emails look good. We use inline if statements for cases where the salary isn't listed or the job doesn\u2019t say if it\u2019s on-site, remote, or hybrid.\n- At the same time, we add the LinkedIn jobs we scraped to a Google Sheet so we can check them later.\n- We combine everything into one list.\n- The Gmail node uses the `map()` function to list all the items we scraped and formatted. It customizes the subject line and heading of the email to include the current date.\n\n## Setup steps\n1. Create a new Google Sheet and add the headers you want. Adjust the Google Sheets node to use your newly created Sheet.\n2. Customize the JSON in the `Get LinkedIn jobs` node. Note that this workflow currently uses the [`LinkedIn Jobs Scraper - No Cookies`](https://apify.com/apimaestro/linkedin-jobs-scraper-api) actor on Apify.  \n   - Leave `date_posted` as is.  \n   - Adjust `keywords` to change the job you want to scrape. You can use Boolean operators like AND or NOT in your search.  \n   - Adjust `limit` to the number of jobs you want to scrape.  \n   - Adjust `location` to match your location.  \n   - Leave `sort` as is to get the most recent jobs first.  \n3. *(Optional)* Edit the HTML in the code node to change how the listings will look in the email.  \n4. Add your email to the Gmail node.\n\n## Requirements\n- [Apify account](https://apify.com/)  \n- Apify community node installed. If you don\u2019t want to install the community node, you can use a regular HTTP node and call the HTTP directly. Check [their API docs](https://docs.apify.com/api/v2) to see what endpoint to call.  \n- Google Sheets API enabled in Google Cloud Console and credentials added to n8n\n- Gmail API enabled in Google Cloud Console credentials added to n8n\n\n## Possible customizations\n- Add full job descriptions to the Google Sheet and email  \n- Continue the flow to create a tailored CV for each job  \n- Use AI to read the job descriptions and pull out the key skills the job posting is asking for  \n"
      },
      "typeVersion": 1
    },
    {
      "id": "27e07561-4655-40bd-aa34-655bfdd3f7f3",
      "name": "Every day at noon...",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -96,
        384
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 12
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "15b0b714-b0e8-4545-b069-076b35566605",
      "name": "Add jobs to Google Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        480,
        208
      ],
      "parameters": {
        "columns": {
          "value": {
            "Date": "={{ $json.posted_at.toDateTime().format('dd MMM yyyy') }}",
            "salary": "={{ $json.salary ? $json.salary : \"Not specified\" }}",
            "company": "={{ $json.company }}",
            "job url": "={{ $json.job_url }}",
            "location": "={{ $json.location ? $json.location : \"Not specified\" }}",
            "job title": "={{ $json.job_title }}",
            "remote or on-site": "={{ $json.work_type ? $json.work_type : \"Not specified\" }}"
          },
          "schema": [
            {
              "id": "Date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "job title",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "job title",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "company",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "company",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "job url",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "job url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "salary",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "salary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "remote or on-site",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "remote or on-site",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "location",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "location",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {
          "useAppend": true
        },
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1IYZk-wt5AUgdJmRcnoA04X23flLyTeyG3AeTsAfWs1U/edit#gid=0",
          "cachedResultName": "Jobs"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1IYZk-wt5AUgdJmRcnoA04X23flLyTeyG3AeTsAfWs1U",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1IYZk-wt5AUgdJmRcnoA04X23flLyTeyG3AeTsAfWs1U/edit?usp=drivesdk",
          "cachedResultName": "Linkedin jobs - n8n demo"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "7f4b0a6a-a5b1-4ceb-b438-7fea120b0d53",
  "connections": {
    "Get LinkedIn jobs": {
      "main": [
        [
          {
            "node": "Set job data & HTML",
            "type": "main",
            "index": 0
          },
          {
            "node": "Add jobs to Google Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set job data & HTML": {
      "main": [
        [
          {
            "node": "Combine items into one list",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Every day at noon...": {
      "main": [
        [
          {
            "node": "Get LinkedIn jobs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Combine items into one list": {
      "main": [
        [
          {
            "node": "Send a message",
            "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

Every day, this workflow scrapes LinkedIn jobs based on your keywords, saves them in a Google Sheet, and sends them by email. The workflow runs every day at noon. The Apify node sends a request to a LinkedIn scraper actor on Apify, which scrapes and returns the data. The code…

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

More Email & Gmail workflows → · Browse all categories →

Related workflows

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

Email & Gmail

YOUR_ID 4. Uses gmail, googleDrive, googleSheets, httpRequest. Scheduled trigger; 53 nodes.

Gmail, Google Drive, Google Sheets +1
Email & Gmail

Looking for a way to track GitHub bounty issues automatically and get notified in real time? This GitHub Bounty Tracker workflow monitors repositories for issues labeled 💎 Bounty, logs them in Google

Google Sheets, HTTP Request, WhatsApp +1
Email & Gmail

This workflow automatically sends a beautifully designed HTML newsletter every Sunday at 8 AM, featuring products currently on sale from your Algolia-powered e-commerce store.

Google Sheets, HTTP Request, Gmail
Email & Gmail

This n8n template demonstrates how to build a Auto Lead Gen & Outreach System for Local Businesses specifically designed to help businesses that don’t have a website yet.

Google Sheets, HTTP Request, Google Drive +1
Email & Gmail

The workflow is triggered automatically every day at 12:00 PM using a Cron node.

RSS Feed Read, Google Sheets, Gmail +1