AutomationFlowsGeneral › Fetch and DM Profile Visitors

Fetch and DM Profile Visitors

Original n8n title: Dm Profile Visitors

Dm-Profile-Visitors. Uses httpRequest, googleSheets. Scheduled trigger; 21 nodes.

Cron / scheduled trigger★★★★☆ complexity21 nodesHTTP RequestGoogle Sheets
General Trigger: Cron / scheduled Nodes: 21 Complexity: ★★★★☆ Added:

This workflow follows the Google Sheets → HTTP Request 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": "f64b448a-f0eb-4dd8-a05f-20711f8f1c26",
      "name": "Workflow Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2304,
        -240
      ],
      "parameters": {
        "width": 588,
        "height": 852,
        "content": "## Send Personalized DMs to LinkedIn Profile Visitors\n\nThis workflow automatically identifies people who visited your LinkedIn profile and sends them personalized direct messages or connection requests based on their connection status.\n\n### Who is this for?\nSales professionals, recruiters, founders, and networkers who want to convert profile visitors into meaningful connections without manual outreach.\n\n### How it works\n1. **Fetch Visitors** \u2013 Retrieves your LinkedIn profile visitors from the past 7 days via ConnectSafely.ai API\n2. **Deduplicate** \u2013 Checks Google Sheets to avoid messaging the same person twice\n3. **Route by Connection** \u2013 Sends DMs to 1st-degree connections or connection requests to others\n4. **Track Progress** \u2013 Logs all outreach to Google Sheets for tracking\n\n### Setup steps\n1. Get your ConnectSafely.ai API key from [connectsafely.ai](https://connectsafely.ai)\n2. Configure the HTTP Bearer Auth credential with your API key\n3. Connect your Google Sheets account and create a sheet with columns: `Name`, `Linkedin URL`, `Status`\n4. Update the Google Sheets node with your sheet ID\n5. Customize the message templates in the Code nodes\n\n### Customization\n| What | Where |\n|------|-------|\n| Message templates | \"Generate DM for Connected User\" and \"Generate Message for New Connection\" Code nodes |\n| Fetch frequency | Schedule Trigger node |\n| Time range for visitors | \"Fetch Profile Visitors\" HTTP Request body |\n\n**Note:** This template requires a ConnectSafely.ai account and API access."
      },
      "typeVersion": 1
    },
    {
      "id": "a0c192b8-e394-4ba1-ab5a-af47abdf6937",
      "name": "Section 1 - Fetch Visitors",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1686,
        84
      ],
      "parameters": {
        "color": 7,
        "width": 460,
        "height": 284,
        "content": "## 1. Fetch & Split Visitors\nRetrieves profile visitors and prepares them for individual processing."
      },
      "typeVersion": 1
    },
    {
      "id": "3a053157-fec1-465e-9154-8189edf61c96",
      "name": "Section 2 - Deduplicate",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1040,
        48
      ],
      "parameters": {
        "color": 7,
        "width": 520,
        "height": 316,
        "content": "## 2. Deduplicate\nChecks if visitor was already contacted to avoid duplicate outreach."
      },
      "typeVersion": 1
    },
    {
      "id": "ae2c1f44-4f82-42fc-bfc5-4243d477f9c8",
      "name": "Section 3 - Send Messages",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -304,
        -176
      ],
      "parameters": {
        "color": 7,
        "width": 844,
        "height": 532,
        "content": "## 3. Route & Send Messages\nSends DMs to connected users or connection requests to new prospects."
      },
      "typeVersion": 1
    },
    {
      "id": "d859a78a-66dd-47b4-ba6a-2471c96aee86",
      "name": "Section 4 - Track Progress",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        576,
        -176
      ],
      "parameters": {
        "color": 7,
        "width": 480,
        "height": 532,
        "content": "## 4. Track & Loop\nLogs outreach to Google Sheets and processes next visitor."
      },
      "typeVersion": 1
    },
    {
      "id": "10ccda8b-2c59-48ea-a2ba-a50725c4f198",
      "name": "Extract Profile ID from URL",
      "type": "n8n-nodes-base.code",
      "position": [
        -272,
        64
      ],
      "parameters": {
        "jsCode": "const url = $('Loop Over Items').first().json.navigationUrl\n\nlet profile_id = null;\n\nif (url) {\n  // Remove query params and trailing slash\n  const cleanUrl = url.split('?')[0].replace(/\\/$/, '');\n\n  // Extract profile ID after /in/\n  const match = cleanUrl.match(/linkedin\\.com\\/in\\/([^/]+)/);\n\n  if (match) {\n    profile_id = match[1];\n  }\n}\n\nreturn {\n  profile_id,\n};\n"
      },
      "typeVersion": 2
    },
    {
      "id": "0d693106-d391-4c15-8eee-c878b5c24e3c",
      "name": "Fetch Profile Visitors",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1392,
        208
      ],
      "parameters": {
        "url": "https://api.connectsafely.ai/linkedin/profile/visitors",
        "method": "POST",
        "options": {},
        "jsonBody": "{\"timeRange\":\"past_7_days\",\"start\":0,\"fetchAll\":true}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth",
        "headerParameters": {
          "parameters": [
            {}
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "7000a0b8-3431-4fca-b696-2c4fee4d0aeb",
      "name": "Weekly Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1616,
        208
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "6a27975a-28b9-4e9d-8cb3-f9c1731b735e",
      "name": "Send Connection Request",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        400,
        160
      ],
      "parameters": {
        "url": "https://api.connectsafely.ai/linkedin/connect",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "profileId",
              "value": "={{ $('Extract Profile ID from URL').item.json.profile_id }}"
            }
          ]
        },
        "genericAuthType": "httpBearerAuth"
      },
      "typeVersion": 4.2
    },
    {
      "id": "22cb5dc4-555d-4cba-8599-d4d128e20180",
      "name": "Check if 1st Degree Connection",
      "type": "n8n-nodes-base.if",
      "position": [
        -48,
        64
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "0cca670d-4ced-4027-98f4-9337048d8a1d",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('Loop Over Items').item.json.connectionDegree }}",
              "rightValue": "1st"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "2fedafe7-567e-4cdc-83db-7da8ce3a9fa6",
      "name": "Send DM to Connected User",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        400,
        -32
      ],
      "parameters": {
        "url": "https://api.connectsafely.ai/linkedin/message",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "recipientProfileId",
              "value": "={{ $('Extract Profile ID from URL').item.json.profile_id }}"
            },
            {
              "name": "message",
              "value": "={{ $json.message }}"
            },
            {
              "name": "messageType",
              "value": "inmail"
            }
          ]
        },
        "genericAuthType": "httpBearerAuth"
      },
      "typeVersion": 4.2
    },
    {
      "id": "af60a93f-7b21-4187-a243-93c648b0f348",
      "name": "Generate Message for New Connection",
      "type": "n8n-nodes-base.code",
      "position": [
        176,
        160
      ],
      "parameters": {
        "jsCode": "// Get recipient name\nconst rawName = $('Loop Over Items').first().json.name || 'there';\nconst name = rawName.trim();\n\n// Sender footer - CUSTOMIZE THIS\nconst footer = `\\n\\n\u2014 Your Name`;\n\n// Message bodies for NON-connected users (connection requests)\n// CUSTOMIZE THESE MESSAGES for your use case\nconst messages = [\n  \"Noticed you checked out my profile, so I thought I'd reach out and connect. I'm working on [YOUR PRODUCT] \u2014 [BRIEF DESCRIPTION]. Happy to connect and share ideas.\",\n\n  \"Saw that you viewed my profile \u2014 always great to connect with like-minded professionals. I'm building [YOUR PRODUCT] to help with [VALUE PROP]. Would love to stay in touch.\",\n\n  \"Thanks for stopping by my profile! I'm currently working on [YOUR PRODUCT], focused on [BENEFIT]. Let's connect and exchange insights.\",\n\n  \"Noticed your visit on my profile and thought I'd say hello. I'm building [YOUR PRODUCT] to help [TARGET AUDIENCE]. Happy to connect!\",\n\n  \"Hey there! I saw you viewed my profile and wanted to connect. I'm working on [YOUR PRODUCT] \u2014 [BRIEF VALUE]. Looking forward to connecting.\"\n];\n\n// Pick random body\nconst body = messages[Math.floor(Math.random() * messages.length)];\n\n// FINAL MESSAGE\nconst finalMessage = `Hey ${name},\\n\\n${body}${footer}`;\n\nreturn {\n  message: finalMessage,\n};\n"
      },
      "typeVersion": 2
    },
    {
      "id": "a80ac098-2ff0-456b-8675-151fc9c0c170",
      "name": "Generate DM for Connected User",
      "type": "n8n-nodes-base.code",
      "position": [
        176,
        -32
      ],
      "parameters": {
        "jsCode": "// Get recipient name\nconst rawName = $('Loop Over Items').first().json.name || 'there';\nconst name = rawName.trim();\n\n// Sender footer - CUSTOMIZE THIS\nconst footer = `\\n\\n\u2014 Your Name`;\n\n// Message bodies for CONNECTED users (direct messages)\n// CUSTOMIZE THESE MESSAGES for your use case\nconst messages = [\n  \"Noticed you recently checked out my profile, so I thought I'd reach out. I've been working on [YOUR PRODUCT] \u2014 [BRIEF DESCRIPTION]. Happy to share if it's relevant.\",\n\n  \"Saw your visit on my profile and wanted to say hello. I'm currently building [YOUR PRODUCT] to help professionals [VALUE PROP].\",\n\n  \"I noticed you viewed my profile, so I thought I'd connect the dots. I've been working on [YOUR PRODUCT], focused on [BENEFIT].\",\n\n  \"Thanks for stopping by my profile! I'm building [YOUR PRODUCT] to help [TARGET AUDIENCE]. Happy to chat if useful.\",\n\n  \"Noticed your profile visit and thought I'd reach out. I'm working on [YOUR PRODUCT] \u2014 [BRIEF VALUE PROPOSITION].\"\n];\n\n// Pick random body\nconst body = messages[Math.floor(Math.random() * messages.length)];\n\n// FINAL MESSAGE\nconst finalMessage = `Hey ${name},\\n\\n${body}${footer}`;\n\nreturn {\n  message: finalMessage,\n};\n"
      },
      "typeVersion": 2
    },
    {
      "id": "f472a968-d6c3-4a94-a323-3bd80c31eaad",
      "name": "Split Visitors Array",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        -1168,
        208
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "visitors"
      },
      "typeVersion": 1
    },
    {
      "id": "0fec9210-7b84-4618-990c-a73462a32be5",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -944,
        208
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "f32e7660-6f6f-4566-ae5d-9da2353f5fe0",
      "name": "Continue to Next Visitor",
      "type": "n8n-nodes-base.noOp",
      "position": [
        848,
        64
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "2a92195e-9b9f-4613-8111-8b3c046f18a8",
      "name": "Wait Between Messages",
      "type": "n8n-nodes-base.wait",
      "position": [
        1072,
        304
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "04b34961-4e22-4d7a-85b4-d8f4e2cb78e5",
      "name": "Log DM Sent to Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        624,
        -32
      ],
      "parameters": {
        "columns": {
          "value": {
            "Name": "={{ $('Loop Over Items').item.json.name }}",
            "Status": "DONE",
            "Linkedin URL": "={{ $('Loop Over Items').item.json.navigationUrl }}"
          },
          "schema": [
            {
              "id": "Name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Linkedin URL",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Linkedin URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Linkedin URL"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "80964e3b-aac9-4950-8cf5-99378edba2e2",
      "name": "Check if Already Contacted",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -720,
        136
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "={{ $json.navigationUrl }}",
              "lookupColumn": "Linkedin URL"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "typeVersion": 4.7,
      "alwaysOutputData": true
    },
    {
      "id": "61c6dbdc-97f1-4bae-8cae-baf823f63803",
      "name": "Skip if Already Contacted",
      "type": "n8n-nodes-base.if",
      "position": [
        -496,
        136
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "149e3e45-fe35-4ef5-bbdd-da8107b82802",
              "operator": {
                "type": "boolean",
                "operation": "false",
                "singleValue": true
              },
              "leftValue": "={{ $json.isEmpty() }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "23d345d5-df7c-41f2-a181-7b731b631a50",
      "name": "Log Connection Request to Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        624,
        160
      ],
      "parameters": {
        "columns": {
          "value": {
            "Name": "={{ $('Loop Over Items').item.json.name }}",
            "Status": "DONE",
            "Linkedin URL": "={{ $('Loop Over Items').item.json.navigationUrl }}"
          },
          "schema": [
            {
              "id": "Name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Linkedin URL",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Linkedin URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Linkedin URL"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "typeVersion": 4.7
    }
  ],
  "connections": {
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "Check if Already Contacted",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log DM Sent to Sheet": {
      "main": [
        [
          {
            "node": "Continue to Next Visitor",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Visitors Array": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait Between Messages": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Profile Visitors": {
      "main": [
        [
          {
            "node": "Split Visitors Array",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Connection Request": {
      "main": [
        [
          {
            "node": "Log Connection Request to Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Weekly Schedule Trigger": {
      "main": [
        [
          {
            "node": "Fetch Profile Visitors",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Continue to Next Visitor": {
      "main": [
        [
          {
            "node": "Wait Between Messages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send DM to Connected User": {
      "main": [
        [
          {
            "node": "Log DM Sent to Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Skip if Already Contacted": {
      "main": [
        [
          {
            "node": "Extract Profile ID from URL",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait Between Messages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if Already Contacted": {
      "main": [
        [
          {
            "node": "Skip if Already Contacted",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Profile ID from URL": {
      "main": [
        [
          {
            "node": "Check if 1st Degree Connection",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if 1st Degree Connection": {
      "main": [
        [
          {
            "node": "Generate DM for Connected User",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Generate Message for New Connection",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate DM for Connected User": {
      "main": [
        [
          {
            "node": "Send DM to Connected User",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log Connection Request to Sheet": {
      "main": [
        [
          {
            "node": "Continue to Next Visitor",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Message for New Connection": {
      "main": [
        [
          {
            "node": "Send Connection Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

How this works

This workflow automates the process of identifying and messaging visitors to your Instagram profile, helping you nurture leads and build connections without manual effort. It's ideal for social media managers, influencers, or small business owners who receive regular profile traffic and want to engage potential customers directly via direct messages. The key step involves extracting the profile ID from your Instagram URL, fetching the list of recent visitors through an HTTP request, and then using Google Sheets to deduplicate and track the outreach, ensuring personalised follow-ups reach unique users efficiently.

Use this workflow when you have a steady stream of Instagram profile visitors and aim to convert them into followers or clients through automated DMs, particularly if you're scheduling weekly runs to avoid overwhelming your account. Avoid it if your profile sees minimal traffic or if Instagram's API policies change, as reliance on HTTP requests could face restrictions. Common variations include adding email integrations for cross-platform tracking or customising message templates for different visitor segments.

About this workflow

Dm-Profile-Visitors. Uses httpRequest, googleSheets. Scheduled trigger; 21 nodes.

Source: https://github.com/ConnectSafelyAI/connectsafely-cookbook/blob/main/n8n/dm-profile-visitors.json — original creator credit. Request a take-down →

More General workflows → · Browse all categories →

Related workflows

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

General

CMS Content Upload Automation. Uses googleSheets, httpRequest. Scheduled trigger; 10 nodes.

Google Sheets, HTTP Request
General

P-ACA 학생 동기화. Uses httpRequest, googleSheets. Scheduled trigger; 9 nodes.

HTTP Request, Google Sheets
General

Google Maps. Uses scheduleTrigger, httpRequest, splitInBatches, googleSheets. Scheduled trigger; 7 nodes.

HTTP Request, Google Sheets
General

Google Maps Business Scraper. Uses scheduleTrigger, googleSheets, httpRequest. Scheduled trigger; 5 nodes.

Google Sheets, HTTP Request
General

RoboNuggets - Faceless POV AI Machine (R24). Uses scheduleTrigger, googleSheets, chainLlm, lmChatOpenAi. Scheduled trigger; 31 nodes.

Google Sheets, Chain Llm, OpenAI Chat +5