AutomationFlowsAI & RAG › Enrich Airtable Company Phones From Website, Linkedin, Google Maps, and Claude

Enrich Airtable Company Phones From Website, Linkedin, Google Maps, and Claude

ByAllan Vaccarizi @growthai on n8n.io

⚠️ Self-hosted only — This template uses a community node (Firecrawl) and cannot run on n8n Cloud.

Event trigger★★★★☆ complexityAI-powered26 nodesAirtable@Mendable/N8N Nodes FirecrawlOutput Parser StructuredAgentHTTP RequestAnthropic Chat
AI & RAG Trigger: Event Nodes: 26 Complexity: ★★★★☆ AI nodes: yes Added:

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

This workflow follows the Agent → Airtable 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": "384359e7-c4a1-44cd-8080-df17333c25dc",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -32,
        0
      ],
      "parameters": {
        "width": 480,
        "height": 800,
        "content": "## Landline phone finder\n\n### How it works\n\n1. A manual trigger fetches records from Airtable and loops over each one individually.\n2. For each record, the workflow scrapes the company website using Firecrawl and cleans the raw markdown output.\n3. An AI agent (Claude) analyzes the cleaned content to attempt extracting a phone number.\n4. If the AI does not find a phone, a LinkedIn scraper API is called as a second fallback, with a check for whether the company profile exists.\n5. If LinkedIn also yields no phone, a Google Maps scraper API is called as a third fallback.\n6. Whichever source finds the phone number, the data is refined via custom code and written back to Airtable; if no phone is found anywhere, the record is updated accordingly.\n\n### Setup steps\n\n- - [ ] Configure Airtable credentials and set the correct base/table in the **Search records**, **Phone found**, and **Phone not found** nodes.\n- - [ ] Add your Firecrawl API key to the **/scrape** node.\n- - [ ] Add your Anthropic API key to the **Anthropic Chat Model** sub-node inside **AI phone finder**.\n- - [ ] Add your Apify API token to both **Linkedin phone finder** (POST to Apify) and **Google maps phone founder** (GET to Apify) HTTP Request nodes.\n- - [ ] Review the **Clean markdown** and **Data refinement** code nodes to ensure field names match your Airtable schema.\n- - [ ] Adjust the conditional logic in **If phone AI**, **If phone Linkedin**, **If Company exist**, and **If google maps phone** nodes to match the exact field paths returned by each API.\n\n### Customization\n\nYou can add or remove fallback sources (LinkedIn, Google Maps) by inserting or bypassing branches after the AI step. The AI prompt inside the Anthropic model can be tuned to target other contact details (email, address) in addition to phone numbers."
      },
      "typeVersion": 1
    },
    {
      "id": "af20d226-1991-42bf-8ca5-8decb085f392",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        480,
        48
      ],
      "parameters": {
        "color": 7,
        "width": 656,
        "height": 304,
        "content": "## Trigger and data fetch\n\nManual trigger that kicks off the workflow, fetches records from Airtable, and feeds them into a loop for per-record processing."
      },
      "typeVersion": 1
    },
    {
      "id": "42d6a000-2dc2-4254-bb7f-72d6bdd81e11",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1184,
        16
      ],
      "parameters": {
        "color": 7,
        "width": 384,
        "height": 320,
        "content": "## Website scrape and clean\n\nScrapes each company's website via Firecrawl and runs custom code to clean and normalise the raw markdown before analysis."
      },
      "typeVersion": 1
    },
    {
      "id": "db2c4d75-2e13-4c1c-9f6c-c64fb9c98c81",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1616,
        0
      ],
      "parameters": {
        "color": 7,
        "width": 528,
        "height": 496,
        "content": "## AI phone extraction\n\nUses an Anthropic Claude AI agent with a structured output parser to extract a phone number from the cleaned website content, then branches based on whether a phone was found."
      },
      "typeVersion": 1
    },
    {
      "id": "c11fbdf8-9154-46ae-a990-5334dc8d9e42",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2176,
        128
      ],
      "parameters": {
        "color": 7,
        "width": 576,
        "height": 320,
        "content": "## LinkedIn fallback lookup\n\nCalls the Apify LinkedIn scraper as a fallback, checks whether the company profile exists, then branches based on whether a phone number was returned."
      },
      "typeVersion": 1
    },
    {
      "id": "74f768f2-bdc1-4921-9057-264c4182d454",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2768,
        208
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 336,
        "content": "## Google Maps fallback lookup\n\nCalls the Apify Google Maps scraper as a final fallback and checks the result for a phone number, routing to success or failure paths."
      },
      "typeVersion": 1
    },
    {
      "id": "15c3300d-6c07-48a3-b8d4-176edd0f3e86",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3200,
        112
      ],
      "parameters": {
        "color": 7,
        "width": 544,
        "height": 544,
        "content": "## Save results to Airtable\n\nRuns custom code to normalise and refine the found phone data, then writes the result back to Airtable \u2014 either as a successful phone match or a not-found record \u2014 before looping to the next item."
      },
      "typeVersion": 1
    },
    {
      "id": "459fd17c-916d-456e-8a83-5440555a415b",
      "name": "When Workflow Runs Manually",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        560,
        176
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "43aa96fe-6e3c-42b4-a2e4-a605cb7d7192",
      "name": "Search Airtable Records",
      "type": "n8n-nodes-base.airtable",
      "position": [
        784,
        176
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appLL5SUhaxtjnSy0",
          "cachedResultUrl": "https://airtable.com/appLL5SUhaxtjnSy0",
          "cachedResultName": "Entreprise construction BOAMP"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblRM03Hfqtn5hLBS",
          "cachedResultUrl": "https://airtable.com/appLL5SUhaxtjnSy0/tblRM03Hfqtn5hLBS",
          "cachedResultName": "Imported table"
        },
        "options": {},
        "operation": "search",
        "filterByFormula": "{Num\u00e9ro de t\u00e9l\u00e9phone fixe} = \"\""
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "498aa9c3-3123-4b96-a510-3b80c5e6c0a6",
      "name": "Scrape Company Website",
      "type": "@mendable/n8n-nodes-firecrawl.firecrawl",
      "onError": "continueErrorOutput",
      "position": [
        1232,
        176
      ],
      "parameters": {
        "url": "={{ $('Loop Over Items').first().json.fields.homepage }}",
        "operation": "scrape",
        "requestOptions": {}
      },
      "credentials": {
        "firecrawlApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a875b03c-1b94-427a-9765-15aa5b80529c",
      "name": "Parse Structured Phone Output",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1840,
        352
      ],
      "parameters": {
        "jsonSchemaExample": "{\"phone\": \"0X XX XX XX XX\"}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "03ec92ea-b6a6-4d20-9421-a4315e66d956",
      "name": "Update Airtable Phone Found",
      "type": "n8n-nodes-base.airtable",
      "position": [
        3568,
        288
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appLL5SUhaxtjnSy0",
          "cachedResultUrl": "https://airtable.com/appLL5SUhaxtjnSy0",
          "cachedResultName": "Entreprise construction BOAMP"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblRM03Hfqtn5hLBS",
          "cachedResultUrl": "https://airtable.com/appLL5SUhaxtjnSy0/tblRM03Hfqtn5hLBS",
          "cachedResultName": "Construction"
        },
        "columns": {
          "value": {
            "id": "={{ $('Loop Over Items').item.json.id }}",
            "Num\u00e9ro de t\u00e9l\u00e9phone fixe": "={{ $json.phone }}"
          },
          "schema": [
            {
              "id": "id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "id",
              "defaultMatch": true
            },
            {
              "id": "company_name",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "company_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "hq_address",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "hq_address",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "linkedin",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "linkedin",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "homepage",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "homepage",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Num\u00e9ro de t\u00e9l\u00e9phone fixe",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Num\u00e9ro de t\u00e9l\u00e9phone fixe",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "id"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update"
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": false,
      "typeVersion": 2.2
    },
    {
      "id": "55821293-742c-42b0-a428-3432b9bc4d5a",
      "name": "Update Airtable Phone Not Found",
      "type": "n8n-nodes-base.airtable",
      "position": [
        3248,
        480
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appLL5SUhaxtjnSy0",
          "cachedResultUrl": "https://airtable.com/appLL5SUhaxtjnSy0",
          "cachedResultName": "Entreprise construction BOAMP"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblRM03Hfqtn5hLBS",
          "cachedResultUrl": "https://airtable.com/appLL5SUhaxtjnSy0/tblRM03Hfqtn5hLBS",
          "cachedResultName": "Construction"
        },
        "columns": {
          "value": {
            "id": "={{ $('Search Airtable Records').item.json.id }}",
            "Num\u00e9ro de t\u00e9l\u00e9phone fixe": "Non dispo"
          },
          "schema": [
            {
              "id": "id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "id",
              "defaultMatch": true
            },
            {
              "id": "company_name",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "company_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "hq_address",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "hq_address",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "linkedin",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "linkedin",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "homepage",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "homepage",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Num\u00e9ro de t\u00e9l\u00e9phone fixe",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Num\u00e9ro de t\u00e9l\u00e9phone fixe",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "id"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update"
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "a02673b6-9cd2-4587-823a-994f7b56e8e2",
      "name": "AI Phone Finder Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1664,
        176
      ],
      "parameters": {
        "text": "={{ $json.markdown_clean }}",
        "options": {
          "systemMessage": "Tu es un agent d'extraction de donn\u00e9es. Tu re\u00e7ois le contenu brut du scraping d'une page web (homepage).\n\nTa mission : extraire un num\u00e9ro de t\u00e9l\u00e9phone s'il est pr\u00e9sent dans le contenu.\n\n---\n\n**R\u00c8GLES D'EXTRACTION**\n\n- Cherche tout num\u00e9ro de t\u00e9l\u00e9phone pr\u00e9sent dans le contenu (format FR ou international)\n- Formats accept\u00e9s : 06 12 34 56 78 / +1234567890 / 0612345678 / etc.\n- Si plusieurs num\u00e9ros sont pr\u00e9sents, retourne le plus pertinent (priorit\u00e9 : num\u00e9ro affich\u00e9 en header/contact, puis le premier trouv\u00e9)\n- Retourne le num\u00e9ro au format 0X XX XX XX XX (ex : 06 12 34 56 78)\n- Si le num\u00e9ro est au format +33, convertis-le : +1234567890 \u2192 06 12 34 56 78\n\n---\n\n**D\u00c9TECTION DE PAGE INVALIDE**\n\nSi le contenu indique que le domaine n'est plus actif (ex : \"domain for sale\", \"parked domain\", \"ce domaine est \u00e0 vendre\", \"404\", \"site en construction\", page de parking de registrar, etc.), consid\u00e8re qu'aucun num\u00e9ro valide ne peut \u00eatre extrait.\n\n---\n\n**FORMAT DE R\u00c9PONSE**\n\nR\u00e9ponds UNIQUEMENT avec le JSON suivant, sans texte autour, sans markdown :\n\nSi num\u00e9ro trouv\u00e9 :\n{\"phone\": \"0X XX XX XX XX\"}\n\nSi aucun num\u00e9ro ou page invalide :\n{\"phone\": \"\"}\n\nRetourne le vide si le num n'est pas trouv\u00e9"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "retryOnFail": true,
      "typeVersion": 3.1
    },
    {
      "id": "23951a0c-e768-437e-b52c-23499dc27e73",
      "name": "If AI Found Phone",
      "type": "n8n-nodes-base.if",
      "position": [
        2000,
        176
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "aec5a866-234c-429d-9295-0e21074436cb",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.output.phone }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "feaf12ff-b837-49c0-84fd-19da890141ce",
      "name": "Fetch LinkedIn Phone via Apify",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2224,
        288
      ],
      "parameters": {
        "url": "https://api.apify.com/v2/acts/UwSdACBp7ymaGUJjS/run-sync-get-dataset-items",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"companies\": [\n    \"{{ $('Loop Over Items').item.json.fields.linkedin }}\"\n  ]\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "apifyApi"
      },
      "credentials": {
        "apifyApi": {
          "name": "<your credential>"
        },
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "executeOnce": false,
      "retryOnFail": true,
      "typeVersion": 4.2,
      "alwaysOutputData": true
    },
    {
      "id": "709b508e-84b3-4a3a-bb00-f466effc49ec",
      "name": "Fetch Google Maps Phone via Apify",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueErrorOutput",
      "position": [
        2816,
        384
      ],
      "parameters": {
        "url": "https://api.apify.com/v2/acts/nwua9Gu5YrADL7ZDj/run-sync-get-dataset-items",
        "options": {},
        "jsonBody": "={\n    \"includeWebResults\": false,\n    \"language\": \"fr\",\n    \"locationQuery\": \"{{ $json.locations[0].city }}, {{ $json.locations[0].postalCode }}\",\n    \"maxCrawledPlacesPerSearch\": 10,\n    \"maximumLeadsEnrichmentRecords\": 0,\n    \"scrapeContacts\": false,\n    \"scrapeDirectories\": false,\n    \"scrapeImageAuthors\": false,\n    \"scrapePlaceDetailPage\": false,\n    \"scrapeReviewsPersonalData\": true,\n    \"scrapeSocialMediaProfiles\": {\n        \"facebooks\": false,\n        \"instagrams\": false,\n        \"tiktoks\": false,\n        \"twitters\": false,\n        \"youtubes\": false\n    },\n    \"scrapeTableReservationProvider\": false,\n    \"searchStringsArray\": [\n        \"{{ $('Loop Over Items').first().json.fields.company_name }}\"\n    ],\n    \"skipClosedPlaces\": false,\n    \"verifyLeadsEnrichmentEmails\": false\n} ",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "apifyApi"
      },
      "credentials": {
        "apifyApi": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": false,
      "typeVersion": 4.4,
      "alwaysOutputData": true
    },
    {
      "id": "98c3d921-0e95-44f2-9084-7fb1d60aeded",
      "name": "If Google Maps Phone Found",
      "type": "n8n-nodes-base.if",
      "position": [
        3024,
        384
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "c868f3fd-ee3d-4256-b92e-cce83bb5e046",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.phone }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "eba1ae0a-daac-42b3-a5cb-ac9dfedf265e",
      "name": "Refine and Merge Phone Data",
      "type": "n8n-nodes-base.code",
      "position": [
        3280,
        288
      ],
      "parameters": {
        "jsCode": "const sources = [\n  $json?.output?.phone,\n  $json?.phone?.number,\n  $json?.phone,\n];\n\nconst phone = sources.find(v => v && typeof v === 'string' && v.trim() !== '');\n\nreturn [{ json: { phone: phone ?? \"\" } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "582ad7c2-87a3-4f0d-bc57-f064483e3941",
      "name": "Clean Scraped Markdown",
      "type": "n8n-nodes-base.code",
      "onError": "continueErrorOutput",
      "position": [
        1424,
        176
      ],
      "parameters": {
        "jsCode": "// Code pour node \"Code\" dans n8n\n// Nettoie le markdown en supprimant les liens, URLs et texte ind\u00e9sirable\n\n// R\u00e9cup\u00e9rer le markdown depuis l'item d'entr\u00e9e\nconst markdown = $input.item.json.data.markdown;\n\n// Fonction pour nettoyer le markdown\nfunction cleanMarkdown(text) {\n  if (!text) return '';\n  \n  let cleaned = text;\n  \n  // 1. Supprimer \"Passer au contenu principal\" et \"Aller au contenu\" (insensible \u00e0 la casse)\n  cleaned = cleaned.replace(/passer au contenu principal/gi, '');\n  cleaned = cleaned.replace(/aller au contenu/gi, '');\n  \n  // 2. Convertir les liens markdown [texte](url) en texte simple\n  // Garde le texte entre [], supprime les [] et (url)\n  cleaned = cleaned.replace(/\\[([^\\]]+)\\]\\([^\\)]+\\)/g, '$1');\n  \n  // 3. Supprimer les crochets restants [] et garder leur contenu\n  cleaned = cleaned.replace(/\\[([^\\]]+)\\]/g, '$1');\n  \n  // 4. Supprimer les URLs standalone (http://, https://, www.)\n  cleaned = cleaned.replace(/https?:\\/\\/[^\\s)]+/g, '');\n  cleaned = cleaned.replace(/www\\.[^\\s)]+/g, '');\n  \n  // 5. Supprimer les parenth\u00e8ses qui contiennent des URLs r\u00e9siduelles\n  cleaned = cleaned.replace(/\\([^)]*(?:http|www)[^)]*\\)/g, '');\n  \n  // 6. Nettoyer les espaces multiples cr\u00e9\u00e9s par les suppressions\n  cleaned = cleaned.replace(/  +/g, ' ');\n  \n  // 7. Nettoyer les lignes vides multiples\n  cleaned = cleaned.replace(/\\n{3,}/g, '\\n\\n');\n  \n  // 8. Supprimer les espaces en d\u00e9but/fin de lignes\n  cleaned = cleaned.split('\\n').map(line => line.trim()).join('\\n');\n  \n  // 9. Supprimer les espaces en d\u00e9but/fin du texte\n  cleaned = cleaned.trim();\n  \n  return cleaned;\n}\n\n// Appliquer le nettoyage\nconst cleanedMarkdown = cleanMarkdown(markdown);\n\n// IMPORTANT : Retourner un TABLEAU contenant l'item\n// Cela pr\u00e9serve le \"pairing\" avec les items pr\u00e9c\u00e9dents\nreturn [{\n  json: {\n    markdown_clean: cleanedMarkdown,\n  }\n}];"
      },
      "typeVersion": 2,
      "alwaysOutputData": false
    },
    {
      "id": "73184d34-bc33-4121-8de7-445251a99176",
      "name": "If Company Exists in LinkedIn",
      "type": "n8n-nodes-base.if",
      "position": [
        2432,
        288
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "88dcacad-f737-48e9-a8d6-5a0a674a7107",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.id }}",
              "rightValue": ""
            },
            {
              "id": "426b4509-b473-4acc-8a38-39fb841f628c",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.phone.number }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "b724d34f-3722-456f-b908-21e9cf4125d2",
      "name": "Claude Sonnet Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
      "position": [
        1696,
        352
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "claude-sonnet-4-6",
          "cachedResultName": "Claude Sonnet 4.6"
        },
        "options": {}
      },
      "credentials": {
        "anthropicApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "1146d7cb-a547-4696-9b2f-1b4bbcfdea76",
      "name": "Sticky Note13",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1472,
        -400
      ],
      "parameters": {
        "color": 7,
        "width": 1024,
        "height": 336,
        "content": "## Need more advanced automation solutions? Contact us for custom enterprise workflows!\n\n# Growth-AI.fr\n\n## https://www.linkedin.com/in/allanvaccarizi/\n## https://www.linkedin.com/in/hugo-marinier-%F0%9F%A7%B2-6537b633/"
      },
      "typeVersion": 1
    },
    {
      "id": "84ff9f6b-3c0f-4c9f-838c-54e034b3fb37",
      "name": "Sticky Note16",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1472,
        -816
      ],
      "parameters": {
        "color": 7,
        "width": 1024,
        "height": 400,
        "content": "![Logo Growth AI](https://cdn.prod.website-files.com/6825df5b20329ba581df4914/68d413c43f8729fa336568a6_Logo_horizontal.png)"
      },
      "typeVersion": 1
    },
    {
      "id": "e7c1e882-7e26-4e58-8f84-2efc970445c2",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        992,
        176
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "d872c352-716f-4a03-8ea7-c8159eeba0ff",
      "name": "If LinkedIn Phone Found",
      "type": "n8n-nodes-base.if",
      "position": [
        2624,
        288
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "f9c6bf23-a70e-47fd-bc68-60faa670fded",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.phone.number }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    }
  ],
  "connections": {
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "Scrape Company Website",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If AI Found Phone": {
      "main": [
        [
          {
            "node": "Refine and Merge Phone Data",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Fetch LinkedIn Phone via Apify",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Claude Sonnet Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Phone Finder Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "AI Phone Finder Agent": {
      "main": [
        [
          {
            "node": "If AI Found Phone",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Clean Scraped Markdown": {
      "main": [
        [
          {
            "node": "AI Phone Finder Agent",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Fetch LinkedIn Phone via Apify",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scrape Company Website": {
      "main": [
        [
          {
            "node": "Clean Scraped Markdown",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Fetch LinkedIn Phone via Apify",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If LinkedIn Phone Found": {
      "main": [
        [
          {
            "node": "Refine and Merge Phone Data",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Fetch Google Maps Phone via Apify",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search Airtable Records": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Google Maps Phone Found": {
      "main": [
        [
          {
            "node": "Refine and Merge Phone Data",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Update Airtable Phone Not Found",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Refine and Merge Phone Data": {
      "main": [
        [
          {
            "node": "Update Airtable Phone Found",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Airtable Phone Found": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When Workflow Runs Manually": {
      "main": [
        [
          {
            "node": "Search Airtable Records",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Company Exists in LinkedIn": {
      "main": [
        [
          {
            "node": "If LinkedIn Phone Found",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Update Airtable Phone Not Found",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Structured Phone Output": {
      "ai_outputParser": [
        [
          {
            "node": "AI Phone Finder Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Fetch LinkedIn Phone via Apify": {
      "main": [
        [
          {
            "node": "If Company Exists in LinkedIn",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Airtable Phone Not Found": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Google Maps Phone via Apify": {
      "main": [
        [
          {
            "node": "If Google Maps Phone Found",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Loop Over Items",
            "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

⚠️ Self-hosted only — This template uses a community node (Firecrawl) and cannot run on n8n Cloud.

Source: https://n8n.io/workflows/15650/ — 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

&gt; ⚠️ Self-hosted only — This template uses a community node () and cannot run on n8n Cloud.

Airtable, HTTP Request, @Mendable/N8N Nodes Firecrawl +3
AI & RAG

RESUME SCREENER. Uses agent, outputParserStructured, lmChatOpenAi, gmailTrigger. Event-driven trigger; 37 nodes.

Agent, Output Parser Structured, OpenAI Chat +7
AI & RAG

This workflow is for SEO managers, content strategists, and digital agencies who need to produce optimised meta tags, H1s, and full content briefs at scale — one per keyword — without doing manual com

Google Sheets, Agent, @Mendable/N8N Nodes Firecrawl +3
AI & RAG

The AI-Powered Shopify SEO Content Automation is an enterprise-grade workflow that transforms product content creation for e-commerce stores. This sophisticated multi-agent system integrates GPT-4o, C

Perplexity Tool, Memory Buffer Window, Agent +15
AI & RAG

Typeform IA - YT. Uses typeformTrigger, agent, lmChatOpenAi, toolWorkflow. Event-driven trigger; 75 nodes.

Typeform Trigger, Agent, OpenAI Chat +7