This workflow corresponds to n8n.io template #11693 — we link there as the canonical source.
This workflow follows the Form Trigger → 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 →
{
"meta": {
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "0ca38d2d-b43f-42ca-839a-829abbe95bc8",
"name": "HTTP Request",
"type": "n8n-nodes-base.httpRequest",
"position": [
432,
-32
],
"parameters": {
"url": "https://www.googleapis.com/customsearch/v1",
"options": {},
"sendQuery": true,
"authentication": "genericCredentialType",
"genericAuthType": "httpBasicAuth",
"queryParameters": {
"parameters": [
{
"name": "cx",
"value": "c0fa13214e7ee42a4"
},
{
"name": "q",
"value": "={{ $('On form submission').item.json.postion }} {{ $('On form submission').item.json.industry }} {{ $('On form submission').item.json.region }} site:linkedin.com/in"
},
{
"name": "start",
"value": "={{ $runIndex == 0 ? $json.currentStartIndex : $node[\"Pagination Check\"].json.startIndex }}"
}
]
}
},
"credentials": {
"httpBasicAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "238cb121-fac4-4257-a039-883db22bb6dd",
"name": "On form submission",
"type": "n8n-nodes-base.formTrigger",
"position": [
-16,
-32
],
"parameters": {
"options": {},
"formTitle": "form",
"formFields": {
"values": [
{
"fieldLabel": "postion",
"placeholder": "position",
"requiredField": true
},
{
"fieldLabel": "industry",
"placeholder": "industry",
"requiredField": true
},
{
"fieldLabel": "region",
"placeholder": "region",
"requiredField": true
}
]
},
"formDescription": "add details like position, industry, place"
},
"typeVersion": 2.3
},
{
"id": "635aa4c7-a268-4117-9abe-7bc0761809e6",
"name": "Code in JavaScript",
"type": "n8n-nodes-base.code",
"position": [
656,
-112
],
"parameters": {
"jsCode": "// Get the response data\nconst response = $input.first().json;\nconst items = response.items || [];\n\n// Track pagination info\nlet nextStartIndex = 1;\nif (response.queries && response.queries.nextPage && response.queries.nextPage[0]) {\n nextStartIndex = response.queries.nextPage[0].startIndex;\n}\n\n// Calculate if we should continue (Google only allows up to 100 results)\nconst hasMoreResults = nextStartIndex <= 100;\n\n// Process the items and include pagination info in each item\nconst results = items.map(item => {\n const titleParts = item.title.split(\" - \");\n const meta = item.pagemap?.metatags?.[0] || {};\n\n // --- Added title cleaning logic ---\n let rawTitle = meta[\"og:title\"] || item.title || \"\";\n const name = titleParts[0] || \"\";\n\n // Remove \"| LinkedIn\" at the end\n let cleanedTitle = rawTitle.replace(/\\s*\\|\\s*LinkedIn\\s*$/i, \"\").trim();\n\n // Remove name from start if present\n if (name && cleanedTitle.toLowerCase().startsWith(name.toLowerCase())) {\n cleanedTitle = cleanedTitle.replace(new RegExp(\"^\" + name + \"\\\\s*-\\\\s*\", \"i\"), \"\").trim();\n }\n // --- End of new logic ---\n\n return {\n name: name || null,\n title: cleanedTitle || null, // <-- cleaned title applied here\n link: item.link || null,\n snippet: meta[\"og:description\"] || item.snippet || null,\n image: item.pagemap?.cse_image?.[0]?.src || item.pagemap?.cse_thumbnail?.[0]?.src || null,\n startIndex: nextStartIndex,\n hasMoreResults: hasMoreResults,\n };\n});\n\n// If there are no results, return at least one item with pagination info\nif (results.length === 0) {\n return [{\n json: {\n name: null,\n title: null,\n link: null,\n snippet: null,\n image: null,\n startIndex: nextStartIndex,\n hasMoreResults: false,\n },\n }];\n}\n\n// Return the processed results\nreturn results.map(r => ({ json: r }));\n"
},
"typeVersion": 2
},
{
"id": "77342f4f-b0f2-4692-a073-050612bd9597",
"name": "Wait",
"type": "n8n-nodes-base.wait",
"position": [
880,
-112
],
"parameters": {
"amount": 3
},
"typeVersion": 1.1
},
{
"id": "e1331432-54a7-4049-bb59-8adb9276614b",
"name": "Code in JavaScript1",
"type": "n8n-nodes-base.code",
"position": [
1552,
-112
],
"parameters": {
"jsCode": "// Get all input items\nconst inputItems = $input.all();\nconsole.log(\"Input items count:\", inputItems.length);\n\nlet nextStartIndex = 2; // default\nlet hasMoreResults = false; // default\n\nif (inputItems && inputItems.length > 0) {\n const firstItem = inputItems[0];\n\n if (firstItem.json) {\n console.log(\"First item JSON:\", JSON.stringify(firstItem.json));\n }\n\n // \u2705 Corrected property names\n if (firstItem.json.startIndex !== undefined) {\n nextStartIndex = firstItem.json.startIndex;\n console.log(\"Found startIndex:\", nextStartIndex);\n }\n\n if (firstItem.json.hasMoreResults !== undefined) {\n hasMoreResults = firstItem.json.hasMoreResults;\n console.log(\"Found hasMoreResults:\", hasMoreResults);\n }\n}\n\n// \u2705 Return pagination control info\nreturn [\n {\n json: {\n continueLoop: hasMoreResults,\n startIndex: nextStartIndex,\n },\n },\n];\n"
},
"typeVersion": 2
},
{
"id": "08aac68e-3f3b-4215-9871-881415635eca",
"name": "Edit Fields",
"type": "n8n-nodes-base.set",
"position": [
208,
-32
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "b021fad7-82e9-4884-878a-f4672117203e",
"name": "currentStartIndex",
"type": "number",
"value": 1
},
{
"id": "cc6ebe1e-49c9-4020-b48c-f41dda365d09",
"name": "maxPages",
"type": "number",
"value": 10
}
]
}
},
"typeVersion": 3.4
},
{
"id": "09eecf87-ccf0-4d87-bc4f-a7d52e6295e8",
"name": "Pagination Check",
"type": "n8n-nodes-base.if",
"position": [
1776,
-32
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "a48fd2c5-c7e0-4da5-adcb-db2acf6972c3",
"operator": {
"type": "boolean",
"operation": "equals"
},
"leftValue": "={{ $json.continueLoop }}",
"rightValue": true
}
]
}
},
"typeVersion": 2.2
},
{
"id": "9fbc0fa8-5441-4fd3-be6d-6f0408e93720",
"name": "Append or update row in sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
1104,
-112
],
"parameters": {
"columns": {
"value": {
"name": "={{ $json.name }}",
"img link": "={{ $json.image }}",
"position": "={{ $json.title }}",
"description": "={{ $json.snippet }}",
"profile links": "={{ $json.link }}",
"searched region": "={{ $('On form submission').item.json.region }}",
"searched industry": "={{ $('On form submission').item.json.industry }}",
"searched position": "={{ $('On form submission').item.json.postion }}"
},
"schema": [
{
"id": "name",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "position",
"type": "string",
"display": true,
"required": false,
"displayName": "position",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "profile links",
"type": "string",
"display": true,
"required": false,
"displayName": "profile links",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "description",
"type": "string",
"display": true,
"required": false,
"displayName": "description",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "img link",
"type": "string",
"display": true,
"required": false,
"displayName": "img link",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "searched position",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "searched position",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "searched industry",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "searched industry",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "searched region",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "searched region",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"name"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.YOUR_AWS_SECRET_KEY_HERE_JdBR0J2M3ydLhkwlnlChh4/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1MeQdveFXA4ihTc7FrFyl_JdBR0J2M3ydLhkwlnlChh4",
"cachedResultUrl": "https://docs.google.YOUR_AWS_SECRET_KEY_HERE_JdBR0J2M3ydLhkwlnlChh4/edit?usp=drivesdk",
"cachedResultName": "linkedin profiles"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "7b0f0978-f1c4-43f0-acf4-0ea53da25c35",
"name": "Edit Fields1",
"type": "n8n-nodes-base.set",
"position": [
1328,
-112
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "dc1488dc-8422-48e2-abf4-9d47a0551c95",
"name": "startIndex",
"type": "string",
"value": "={{ $('Code in JavaScript').item.json.startIndex }}"
},
{
"id": "b0fdc0e8-e780-4460-b710-c8bdd3f00c3e",
"name": "hasMoreResults",
"type": "boolean",
"value": "={{ $('Code in JavaScript').item.json.hasMoreResults }}"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "ebc78822-5d95-4ade-8273-be9005093f3a",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-688,
-256
],
"parameters": {
"width": 592,
"height": 528,
"content": "## Scrape LinkedIn Profiles to Google Sheets\n\n### How it works\\n1. You provide a position, industry, and region via a web form.\n2. The workflow performs a Google Custom Search for matching LinkedIn profiles.\n3. It extracts key profile information such as name, title, link, and description from the search results.\n4. All found profiles are appended or updated in your specified Google Sheet.\n5. The workflow automatically fetches multiple pages of results, stopping when no more are available or the Google Search API limit is reached.\n\n### Setup\n- [ ] Connect your Google Sheets account.\n- [ ] Add your Google Custom Search API Key and Search Engine ID (CX).\n- [ ] Select your Google Sheet document and the target sheet within the \\\"Append or update row in sheet\\\" node.\n- [ ] Ensure your Google Sheet has columns for: Name, Position, Profile Links, Description, Image Link, Searched Position, Searched Industry, and Searched Region.\n- [ ] Fill out the \\\"On form submission\\\" trigger form with your desired search criteria to initiate the workflow."
},
"typeVersion": 1
},
{
"id": "a767f679-5774-486e-9e83-24362be38268",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-64,
-112
],
"parameters": {
"color": 7,
"width": 416,
"height": 272,
"content": "## get the search data "
},
"typeVersion": 1
},
{
"id": "3667733b-a530-44a1-810b-bcdf627faf84",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
368,
-192
],
"parameters": {
"color": 7,
"width": 1616,
"height": 384,
"content": "## geather linkedin profile and update sheets\nsetup:\nadd custom search api key in http node"
},
"typeVersion": 1
}
],
"connections": {
"Wait": {
"main": [
[
{
"node": "Append or update row in sheet",
"type": "main",
"index": 0
}
]
]
},
"Edit Fields": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
]
]
},
"Edit Fields1": {
"main": [
[
{
"node": "Code in JavaScript1",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request": {
"main": [
[
{
"node": "Code in JavaScript",
"type": "main",
"index": 0
}
]
]
},
"Pagination Check": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
]
]
},
"Code in JavaScript": {
"main": [
[
{
"node": "Wait",
"type": "main",
"index": 0
}
]
]
},
"On form submission": {
"main": [
[
{
"node": "Edit Fields",
"type": "main",
"index": 0
}
]
]
},
"Code in JavaScript1": {
"main": [
[
{
"node": "Pagination Check",
"type": "main",
"index": 0
}
]
]
},
"Append or update row in sheet": {
"main": [
[
{
"node": "Edit Fields1",
"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.
googleSheetsOAuth2ApihttpBasicAuth
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This template is ideal for recruiters, founders, sales teams, and lead-generation specialists who want to quickly collect LinkedIn profiles based on role, industry, and region. It is perfect for users who want profile lists for outreach, research, hiring, or market analysis…
Source: https://n8n.io/workflows/11693/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Disclaimer: this workflow only works on self-hosted instances due to the file system usage.
This n8n workflow automates the process of scraping job listings from both LinkedIn and Indeed platforms simultaneously, combining results, and exporting data to Google Sheets for comprehensive job ma
💼 LinkedIn Job Finder Automation using Bright Data API & Google Sheets
This n8n workflow automatically converts LinkedIn video URLs into downloadable MP4 files using the LinkedIn Video Downloader API, uploads them to Google Drive with public access, and logs both the ori
LinkedIn Hiring Signal Scraper — Jobs & Prospecting Using Bright Data