AutomationFlowsWeb Scraping › Scrape Tunisia It Job Listings with Groq, Firecrawl, Airtable, and Resend

Scrape Tunisia It Job Listings with Groq, Firecrawl, Airtable, and Resend

ByDhia Kassab @meddhiakassab on n8n.io

This workflow runs daily or via chat to scrape Tunisia-focused IT job listings from predefined company career pages using Firecrawl, saves results into Airtable tables, and emails a daily digest through Resend, with job parsing and orchestration handled by a Groq-powered AI…

Cron / scheduled trigger★★★★☆ complexityAI-powered21 nodesAgentGroq ChatMemory Buffer WindowTool Http RequestAgent ToolChat TriggerHTTP Request
Web Scraping Trigger: Cron / scheduled Nodes: 21 Complexity: ★★★★☆ AI nodes: yes Added:

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

This workflow follows the Agent → Agenttool 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": "CfYu2beB05cnvXlQ",
  "name": "Tunisia IT Jobs Autopilot \u2014 AI Scraper + Airtable + Daily Digest",
  "tags": [],
  "nodes": [
    {
      "id": "f47e6bb5-d16e-4f02-9f1e-e4b74f5db8a6",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        352,
        -96
      ],
      "parameters": {
        "width": 480,
        "height": 800,
        "content": "## Tunisia IT Jobs Autopilot \u2014 AI Scraper + Airtable + Daily Digest\n\n### How it works\n\nThis workflow monitors Tunisian IT job opportunities by scraping company career pages with an AI agent, saving relevant findings to Airtable, and producing either a daily email digest or a chat response. It can run automatically every morning at 7 AM, rotating through a company list, or be invoked manually through chat. After the AI agent completes its scraping and saving work, the workflow branches based on whether the execution was scheduled or chat-based.\n\n### Setup steps\n\n- Add valid Firecrawl, Airtable, Groq, and Resend API credentials in the relevant nodes or variables used by the configuration node.\n- Configure the Airtable base ID, target table/fields, and permissions so the Airtable saver agent can create or update job records.\n- Set the recipient email address for the Resend email request and ensure the sending domain/API key is verified in Resend.\n- Enable the daily schedule trigger and test both the scheduled path and chat-triggered path before production use.\n\n### Customization\n\nAdjust the company rotation list, scraping prompts, Airtable schema, email digest format, and schedule time to match the target job market or preferred notification cadence."
      },
      "typeVersion": 1
    },
    {
      "id": "8761063b-87a4-4e23-915d-36770ec9a3fc",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        880,
        -96
      ],
      "parameters": {
        "color": 7,
        "width": 368,
        "height": 592,
        "content": "## Start and company selection\n\nContains the two workflow entry points: a daily 7 AM schedule and an on-demand chat trigger. The scheduled path also rotates through the configured company list so one company is checked per day before continuing."
      },
      "typeVersion": 1
    },
    {
      "id": "d8aa0e31-174d-4616-95c0-7368f64e66a1",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1296,
        176
      ],
      "parameters": {
        "color": 7,
        "width": 912,
        "height": 560,
        "content": "## Configure and scrape jobs\n\nSets the required API keys and runtime configuration, then runs the AI agent that scrapes company career pages, interprets results with the Groq model, keeps short-term memory, and saves found jobs to Airtable through the agent tool."
      },
      "typeVersion": 1
    },
    {
      "id": "067d572d-d75b-4932-a888-be3e8e9e9246",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2240,
        -48
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 560,
        "content": "## Route final response\n\nChecks whether the run came from the schedule or chat. Scheduled runs send a daily digest email through Resend, while chat-triggered runs return the result back through the chat response path."
      },
      "typeVersion": 1
    },
    {
      "id": "4e7f73ce-a6c3-41b1-8038-5a856e3e889a",
      "name": "Configure API and Email Settings",
      "type": "n8n-nodes-base.set",
      "position": [
        1344,
        336
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "asgn-fc-001",
              "name": "firecrawlApiKey",
              "type": "string",
              "value": "test"
            },
            {
              "id": "asgn-at-001",
              "name": "airtableApiKey",
              "type": "string",
              "value": "test"
            },
            {
              "id": "asgn-at-002",
              "name": "airtableBaseId",
              "type": "string",
              "value": "test"
            },
            {
              "id": "asgn-bv-005",
              "name": "recipientEmail",
              "type": "string",
              "value": "user@example.com"
            },
            {
              "id": "asgn-rs-001",
              "name": "resendApiKey",
              "type": "string",
              "value": "test"
            },
            {
              "id": "asgn-rs-002",
              "name": "fromEmail",
              "type": "string",
              "value": "Career Digest <user@example.com>"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "6b275a3f-fcfa-4b88-af74-f48f669932db",
      "name": "Tunisia Job Analyzer Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1616,
        336
      ],
      "parameters": {
        "text": "={{ $json.chatInput }}",
        "options": {
          "systemMessage": "You are a career-opportunities assistant. You find job listings from a fixed set of company career pages and can save them to Airtable.\n\nTOOLS\n- Scrape Career Page: scrapes ONE career-page URL and returns its content. You only supply the URL; call it once per URL.\n- Airtable Saver Agent: a sub-agent that saves parsed jobs to Airtable. Hand it a clean JSON array of jobs plus a target table name.\n\nALLOWED URLs \u2014 use EXACTLY as written, including every query parameter:\n\ud83c\udfe2 Sagemcom Tunisia (paginated \u2014 3 pages):\n- https://careers-tunisia.sagemcom.com/offre-de-emploi/liste-offres.aspx?page=1&LCID=1036\n- https://careers-tunisia.sagemcom.com/offre-de-emploi/liste-offres.aspx?page=2&LCID=1036\n- https://careers-tunisia.sagemcom.com/offre-de-emploi/liste-offres.aspx?page=3&LCID=1036\n\n\ud83c\udfe2 InstaDeep:\n- https://instadeep.com/about-us/careers/\n\n\ud83c\udfe2 PwC Tunisia:\n- https://tunisie.pwc.fr/fr/pwc-tunisie/carrieres/experienced-jobs.html\n\n\ud83c\udfe2 Planisware:\n- https://careers.planisware.com/en/\n\n\ud83c\udfe2 MaibornWolff:\n- https://karriere.maibornwolff.de/en/jobs/\n\n\ud83c\udfe2 Infor:\n- https://careers.infor.com/#js-careers-jobs-block\n\n\ud83c\udfe2 VNeuron (paginated \u2014 3 pages):\n- https://vneuron-group.careers-page.com/\n- https://vneuron-group.careers-page.com/?page=2\n- https://vneuron-group.careers-page.com/?page=3\n\n\ud83c\udfe2 Inetum:\n- https://www.inetum.com/global/en/careers/jobs.html?list-9b828c901c_page=1\n\n\ud83c\udfe2 Vermeg:\n- https://www.vermeg.com/featured-jobs/\n\n\ud83c\udfe2 Medius (Tunisia filter):\n- https://career.medius.com/fr/jobs?split_view=true&query=&country=Tunisia\n\n\ud83c\udfe2 Sofrecom:\n- https://www.sofrecom.com/carrieres/travailler-chez-sofrecom.html\n\nHOW TO WORK (be efficient \u2014 minimise tool calls)\n1. Scrape ONLY what the user asks for. Never scrape every company or every page unless explicitly told to.\n2. Paginated sites (Sagemcom, VNeuron): make one Scrape Career Page call per page URL.\n3. Parse each scrape into structured jobs with these keys: Job Title, Company, Location, Description, URL. Drop nav/cookie/boilerplate text. NEVER invent listings \u2014 report only what was actually scraped. If a page is empty or irrelevant, say so plainly.\n4. Reuse what you already have: do not re-scrape a URL whose results are already in this conversation.\n5. Present results compactly, one line each: Title \u2014 Location \u2014 short description.\n\nSAVING TO AIRTABLE\n6. Save only when the user asks (or these instructions require it). Scrape and parse FIRST, then call Airtable Saver Agent ONCE per company.\n7. Call it with a SINGLE `payload` argument that is a JSON OBJECT of the form:\n   { \"tableName\": \"<CompanyName>\", \"jobs\": [ { \"Job Title\": \"...\", \"Company\": \"...\", \"Location\": \"...\", \"Description\": \"...\", \"URL\": \"...\" }, ... ] }\n   Use the company name as tableName (e.g. Sagemcom_Tunisia, PwC_Tunisia, Vermeg). Do NOT pass jobs as a separate top-level string \u2014 everything goes inside the one payload object.\n8. Airtable accepts max 10 records per write; the saver agent handles batching, so you may pass all jobs for one company in a single payload."
        },
        "promptType": "define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "53db373e-7d5c-42e2-a01b-e7f14fa120d8",
      "name": "Groq Chat Interaction Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGroq",
      "position": [
        1584,
        592
      ],
      "parameters": {
        "model": "llama-3.3-70b-versatile",
        "options": {}
      },
      "credentials": {
        "groqApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "e6d00def-568a-446d-880a-aa749fac2dd3",
      "name": "Memory Buffer Manager",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        1744,
        592
      ],
      "parameters": {
        "sessionKey": "={{ $json.sessionId }}",
        "sessionIdType": "customKey",
        "contextWindowLength": 10
      },
      "typeVersion": 1.3
    },
    {
      "id": "85a18e9c-09c6-46ab-b038-8a9a76d9da05",
      "name": "Scrape Job Listings",
      "type": "@n8n/n8n-nodes-langchain.toolHttpRequest",
      "position": [
        1904,
        592
      ],
      "parameters": {
        "url": "https://api.firecrawl.dev/v1/scrape",
        "method": "POST",
        "jsonBody": "={\n  \"url\": \"{url}\",\n  \"formats\": [\"markdown\"],\n  \"onlyMainContent\": true\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "toolDescription": "Scrapes ONE career-page URL with Firecrawl and returns its main content as markdown. Pass a single exact URL from the allowed list per call.",
        "parametersHeaders": {
          "values": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $('Configure API and Email Settings').first().json.firecrawlApiKey }}",
              "valueProvider": "fieldValue"
            }
          ]
        },
        "placeholderDefinitions": {
          "values": [
            {
              "name": "url",
              "description": "The exact career-page URL to scrape, copied verbatim (including all query parameters) from the allowed list in the system prompt."
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "f908c05e-0b6d-45c0-99a2-d642ba44da5d",
      "name": "Airtable Record Saver",
      "type": "@n8n/n8n-nodes-langchain.agentTool",
      "position": [
        2112,
        592
      ],
      "parameters": {
        "text": "=Process this Airtable save request.\nPayload (JSON): {{ JSON.stringify($fromAI('payload', 'A JSON OBJECT with exactly two keys: \"tableName\" (string = company name, e.g. Sagemcom_Tunisia) and \"jobs\" (an array of job objects, each with Job Title, Company, Location, Description, URL).', 'json')) }}",
        "options": {
          "systemMessage": "You store job postings in Airtable. You receive a JSON payload with two keys: `tableName` (string) and `jobs` (an array of job objects). Be deterministic and minimise tool calls.\n\nEXECUTION PLAN\n1. Read `tableName` and `jobs` from the payload.\n2. Call `Airtable Check Table Tool` ONCE with the table name to see whether it already exists.\n3. If \u2014 and only if \u2014 it does not exist, call `Airtable Create Table Tool` ONCE (provide just the table name).\n4. Call `Airtable Save Jobs Tool` to insert the records. Pass `tableName`, and build the body as a JSON OBJECT: {\"records\":[{\"fields\":{\"Job Title\":\"...\",\"Company\":\"...\",\"Location\":\"...\",\"Description\":\"...\",\"URL\":\"...\"}}]}. Max 10 records per call \u2014 if `jobs` has more, make multiple calls of up to 10.\n5. Do NOT re-check or re-create a table you already confirmed/created in this run.\n6. Finish with ONE short summary: how many jobs were saved and to which table.\n\nIf a tool returns an error, report the exact error message instead of retrying blindly.\n\nIMPORTANT: Use ONLY the real values from the payload. NEVER invent or use placeholder/example values such as \"example_table_name\", \"example_job_title\", or \"example_company\". The tableName you write to must be the payload's tableName, and every record's fields must come from the payload's jobs array."
        },
        "toolDescription": "A specialized sub-agent for saving scraped job listings to Airtable. It will automatically check if the target table exists, and if not, create it first with standard job-posting columns [Job Title, Company, Location, Description, URL] before inserting the rows."
      },
      "typeVersion": 2.2
    },
    {
      "id": "13e573de-0027-473a-9486-169892226685",
      "name": "Airtable Groq Interaction",
      "type": "@n8n/n8n-nodes-langchain.lmChatGroq",
      "position": [
        2048,
        768
      ],
      "parameters": {
        "model": "llama-3.3-70b-versatile",
        "options": {}
      },
      "credentials": {
        "groqApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "9f5c2788-73b6-45b6-8f1b-1120ca071a97",
      "name": "Check Airtable Table Existence",
      "type": "@n8n/n8n-nodes-langchain.toolHttpRequest",
      "position": [
        2256,
        784
      ],
      "parameters": {
        "url": "=https://api.airtable.com/v0/meta/bases/{{ $('Configure API and Email Settings').first().json.airtableBaseId }}/tables?lookupTable={tableName}",
        "sendHeaders": true,
        "toolDescription": "Lists all tables in the Airtable base so you can check whether the target table already exists. Pass the table name you are looking for.",
        "optimizeResponse": true,
        "parametersHeaders": {
          "values": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $('Configure API and Email Settings').first().json.airtableApiKey }}",
              "valueProvider": "fieldValue"
            }
          ]
        },
        "placeholderDefinitions": {
          "values": [
            {
              "name": "tableName",
              "description": "The exact table name you are checking for, e.g. Sagemcom_Tunisia."
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "d87df0fb-46e4-4cf2-b6da-f157da3bd7a7",
      "name": "Create Airtable Table",
      "type": "@n8n/n8n-nodes-langchain.toolHttpRequest",
      "position": [
        2608,
        784
      ],
      "parameters": {
        "url": "=https://api.airtable.com/v0/meta/bases/{{ $('Configure API and Email Settings').first().json.airtableBaseId }}/tables",
        "method": "POST",
        "jsonBody": "={\n  \"name\": \"{tableName}\",\n  \"description\": \"Saved scraped job postings\",\n  \"fields\": [\n    { \"name\": \"Job Title\", \"type\": \"singleLineText\" },\n    { \"name\": \"Company\", \"type\": \"singleLineText\" },\n    { \"name\": \"Location\", \"type\": \"singleLineText\" },\n    { \"name\": \"Description\", \"type\": \"multilineText\" },\n    { \"name\": \"URL\", \"type\": \"url\" }\n  ]\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "toolDescription": "Creates a new table in the Airtable base with the standard job columns (Job Title, Company, Location, Description, URL). Provide ONLY the table name; columns are fixed.",
        "parametersHeaders": {
          "values": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $('Configure API and Email Settings').first().json.airtableApiKey }}",
              "valueProvider": "fieldValue"
            },
            {
              "name": "Content-Type",
              "value": "application/json",
              "valueProvider": "fieldValue"
            }
          ]
        },
        "placeholderDefinitions": {
          "values": [
            {
              "name": "tableName",
              "description": "The exact name for the new table, e.g. Sagemcom_Tunisia."
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "ccd87803-5e35-484d-b7dd-e4378bcf6b79",
      "name": "Save Jobs to Airtable",
      "type": "@n8n/n8n-nodes-langchain.toolHttpRequest",
      "position": [
        2432,
        784
      ],
      "parameters": {
        "url": "=https://api.airtable.com/v0/{{ $('Configure API and Email Settings').first().json.airtableBaseId }}/{tableName}",
        "method": "POST",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "model",
        "toolDescription": "Inserts job records into an existing Airtable table. The `tableName` is the target table. The request BODY must be a JSON object of the form {\"records\": [ {\"fields\": {\"Job Title\":\"...\",\"Company\":\"...\",\"Location\":\"...\",\"Description\":\"...\",\"URL\":\"...\"}} ]} with up to 10 records per call.",
        "parametersHeaders": {
          "values": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $('Configure API and Email Settings').first().json.airtableApiKey }}",
              "valueProvider": "fieldValue"
            },
            {
              "name": "Content-Type",
              "value": "application/json",
              "valueProvider": "fieldValue"
            }
          ]
        },
        "placeholderDefinitions": {
          "values": [
            {
              "name": "tableName",
              "description": "The target table name (= company name), e.g. Sagemcom_Tunisia."
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "cc2e820e-db54-42d7-bdec-8a8c6cf85633",
      "name": "Trigger Daily at 7AM",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        928,
        336
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 7
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "f05ae0f6-1a62-4473-9616-66e480204ed0",
      "name": "Rotate Company Selection",
      "type": "n8n-nodes-base.code",
      "position": [
        1104,
        336
      ],
      "parameters": {
        "jsCode": "// Sequentially rotate through the company list, one per day.\n// State persists across scheduled executions via workflow static data.\nconst companies = [\n  'Sagemcom Tunisia', 'InstaDeep', 'PwC Tunisia', 'Planisware', 'MaibornWolff',\n  'Infor', 'VNeuron', 'Inetum', 'Vermeg', 'Medius', 'Sofrecom'\n];\n\nconst sd = $getWorkflowStaticData('global');\nif (typeof sd.companyIndex !== 'number') sd.companyIndex = 0;\n\nconst company = companies[sd.companyIndex % companies.length];\nsd.companyIndex = (sd.companyIndex + 1) % companies.length;  // advance for next run\n\n// For a RANDOM company instead of sequential, replace the two lines above with:\n// const company = companies[Math.floor(Math.random() * companies.length)];\n\nconst tableName = company.replace(/\\s+/g, '_');\nconst today = new Date().toISOString().slice(0, 10);\n\nreturn [{\n  json: {\n    company,\n    tableName,\n    sessionId: 'daily-' + today,\n    chatInput: `Scrape the ${company} career page (scrape every page if it is paginated), then save all the jobs you find to Airtable in a table named ${tableName}. After saving, give me the complete list of jobs with title, location and a short description.`\n  }\n}];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "705cab5d-339c-4f1a-bf27-a582b3bdb572",
      "name": "Chat Message Trigger",
      "type": "@n8n/n8n-nodes-langchain.chatTrigger",
      "position": [
        928,
        128
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1.1
    },
    {
      "id": "9bc78977-7331-47d8-8dfe-8ff8ff8f00c5",
      "name": "Check If Scheduled Run",
      "type": "n8n-nodes-base.if",
      "position": [
        2288,
        336
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-sched-001",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $('Rotate Company Selection').isExecuted }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "303edb2d-abb2-41b1-8f61-fe90a7ff62f5",
      "name": "Handle Chat Response",
      "type": "n8n-nodes-base.noOp",
      "position": [
        2512,
        352
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "12248786-3814-497a-b4ed-0fc62dcbf012",
      "name": "Send Email Via Resend API",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2512,
        160
      ],
      "parameters": {
        "url": "https://api.resend.com/emails",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"from\": \"{{ $('Configure API and Email Settings').first().json.fromEmail }}\",\n  \"to\": [\"{{ $('Configure API and Email Settings').first().json.recipientEmail }}\"],\n  \"subject\": \"Daily Career Digest \u2014 {{ $('Rotate Company Selection').first().json.company }} \u2014 {{ $now.format('yyyy-MM-dd') }}\",\n  \"text\": {{ JSON.stringify($json.output) }}\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $('Configure API and Email Settings').first().json.resendApiKey }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "a843528d-091a-4efd-862e-ee0ab7934c2d",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        352,
        736
      ],
      "parameters": {
        "width": 672,
        "height": 368,
        "content": "@[youtube](32BjSarsgLQ)"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "b1eca583-0460-40a3-bc2c-4b1a59f8fb25",
  "nodeGroups": [],
  "connections": {
    "Scrape Job Listings": {
      "ai_tool": [
        [
          {
            "node": "Tunisia Job Analyzer Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Chat Message Trigger": {
      "main": [
        [
          {
            "node": "Configure API and Email Settings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trigger Daily at 7AM": {
      "main": [
        [
          {
            "node": "Rotate Company Selection",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Airtable Record Saver": {
      "ai_tool": [
        [
          {
            "node": "Tunisia Job Analyzer Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Create Airtable Table": {
      "ai_tool": [
        [
          {
            "node": "Airtable Record Saver",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Memory Buffer Manager": {
      "ai_memory": [
        [
          {
            "node": "Tunisia Job Analyzer Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Save Jobs to Airtable": {
      "ai_tool": [
        [
          {
            "node": "Airtable Record Saver",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Check If Scheduled Run": {
      "main": [
        [
          {
            "node": "Send Email Via Resend API",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handle Chat Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Rotate Company Selection": {
      "main": [
        [
          {
            "node": "Configure API and Email Settings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Airtable Groq Interaction": {
      "ai_languageModel": [
        [
          {
            "node": "Airtable Record Saver",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Tunisia Job Analyzer Agent": {
      "main": [
        [
          {
            "node": "Check If Scheduled Run",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Groq Chat Interaction Model": {
      "ai_languageModel": [
        [
          {
            "node": "Tunisia Job Analyzer Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Check Airtable Table Existence": {
      "ai_tool": [
        [
          {
            "node": "Airtable Record Saver",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Configure API and Email Settings": {
      "main": [
        [
          {
            "node": "Tunisia Job Analyzer Agent",
            "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

This workflow runs daily or via chat to scrape Tunisia-focused IT job listings from predefined company career pages using Firecrawl, saves results into Airtable tables, and emails a daily digest through Resend, with job parsing and orchestration handled by a Groq-powered AI…

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

More Web Scraping workflows → · Browse all categories →

Related workflows

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

Web Scraping

Turn any Amazon India product URL into a fully-edited 10-second lifestyle video and auto-publish it to Instagram, Facebook, X (Twitter), LinkedIn, YouTube, and Threads — with platform-optimized captio

HTTP Request, @Apify/N8N Nodes Apify, OpenRouter Chat +3
Web Scraping

This SEO Keyword Monitoring workflow template is perfect for SEO professionals, digital marketing agencies, website owners, and content strategists who need to track their search rankings and get acti

HTTP Request, Form Trigger, Groq Chat +2
Web Scraping

Perfect for social media managers, content creators, and personal brands who want to stay relevant on X without manually tracking trends or writing posts every day. The workflow runs 3 times daily by

Data Table, @Apify/N8N Nodes Apify, HTTP Request +3
Web Scraping

This workflow runs daily to scrape competitor Shopify app reviews via Apify, logs and deduplicates new low-rated reviews in Google Sheets, looks up the reviewer’s website with Serper, enriches contact

OpenAI Chat, Google Sheets, Hunter +5
Web Scraping

Visual Regression Testing With Apify And Ai Vision Model. Uses googleDrive, lmChatGoogleGemini, outputParserStructured, stickyNote. Scheduled trigger; 34 nodes.

Google Drive, Google Gemini Chat, Output Parser Structured +4