Google Sheets + Apify: leads enriched from websites
You find a list of promising company websites, then lose an afternoon digging for a “Contact” page, copying emails, second-guessing phone numbers, and pasting everything into a sheet that still isn’t outreach-ready.
Sales teams feel it when pipeline is light. Recruiters hit the same wall when they need hiring manager contacts. And growth folks doing list building know the pain too. This Apify lead enrichment automation turns a simple list of domains into a clean Google Sheets lead file with emails, phone numbers, and source pages.
Below you’ll see exactly what the workflow does, what you get out the other side, and how to set it up without turning this into a week-long “automation project.”
How This Automation Works
The full n8n workflow, from trigger to final output:
n8n Workflow Template: Google Sheets + Apify: leads enriched from websites
flowchart LR
subgraph sg0["When clicking ‘Execute workflow’ Flow"]
direction LR
n0@{ icon: "mdi:play-circle", form: "rounded", label: "When clicking ‘Execute workf..", pos: "b", h: 48 }
n1@{ icon: "mdi:swap-vertical", form: "rounded", label: "Set google sheet URL & origi..", pos: "b", h: 48 }
n2["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/merge.svg' width='40' height='40' /></div><br/>wait for previous nodes to f.."]
n3["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>format data for Apify INPUT .."]
n4@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Run Actor on Apify", pos: "b", h: 48 }
n5@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Get Results from Apify", pos: "b", h: 48 }
n6@{ icon: "mdi:database", form: "rounded", label: "Add emails, phones, socials...", pos: "b", h: 48 }
n7@{ icon: "mdi:database", form: "rounded", label: "Create new sheet for founded..", pos: "b", h: 48 }
n8@{ icon: "mdi:database", form: "rounded", label: "Get website URLs from first ..", pos: "b", h: 48 }
n4 --> n5
n5 --> n6
n3 --> n4
n8 --> n2
n2 --> n3
n0 --> n1
n1 --> n7
n1 --> n8
n7 --> n2
end
%% Styling
classDef trigger fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
classDef ai fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
classDef aiModel fill:#e8eaf6,stroke:#3f51b5,stroke-width:2px
classDef decision fill:#fff8e1,stroke:#f9a825,stroke-width:2px
classDef database fill:#fce4ec,stroke:#c2185b,stroke-width:2px
classDef api fill:#fff3e0,stroke:#e65100,stroke-width:2px
classDef code fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef disabled stroke-dasharray: 5 5,opacity: 0.5
class n0 trigger
class n4,n5 decision
class n6,n7,n8 database
class n3 code
classDef customIcon fill:none,stroke:none
class n2,n3 customIcon
The Problem: Website contact research is slow (and messy)
Website-based lead research looks easy until you do it at any real volume. One site has emails on the footer. Another hides them in a PDF. A third only lists a contact form, so you go hunting on “About,” “Team,” and random subpages. Then you paste what you found into Google Sheets, but you forget where you found it, or you grab the wrong address (info@ instead of a direct contact). After 20 websites, you’re tired, your sheet is inconsistent, and outreach gets delayed.
The time sink isn’t just the browsing. It’s the constant context switching and clean-up.
- Each website turns into 5–10 clicks and a bunch of copy-paste, which adds up fast over a list of 100 domains.
- You end up with partial data, so someone has to “finish the sheet” before anyone can send a first email.
- Source tracking is usually missing, which makes verification and QA annoyingly manual.
- Doing this weekly is how small errors become a permanent, ugly CRM problem.
The Solution: Enrich your website list with Apify, then write back to Sheets
This workflow starts with a Google Sheet that contains one website URL or domain per row. When you run it, n8n reads that list, prepares a payload, and sends it to Apify’s Email & Phone Extractor actor. Apify then crawls each site to find contact details like emails and phone numbers, plus useful context such as the source pages where those details were found (and often social links like LinkedIn or Twitter). When Apify finishes, the workflow pulls the dataset back into n8n and appends everything into a brand-new Google Sheet tab, already structured as a lead file.
The workflow begins when you manually launch it in n8n. It creates a fresh output sheet, fetches your website list, runs the Apify extraction, then writes the results back into Google Sheets so your team can filter, verify, and start outreach.
What You Get: Automation vs. Results
| What This Workflow Automates | Results You’ll Get |
|---|---|
|
|
Example: What This Looks Like
Say you need contacts for 80 target accounts. Manually, you might spend about 8 minutes per website between searching, copying, and formatting, which is roughly 10 hours of work. With this workflow, you paste the 80 domains into Google Sheets, hit “Execute” in n8n (about 2 minutes), and let Apify run in the background. Even if the scrape takes a while, you’re not stuck doing repetitive browsing, and you still end up with a new sheet tab containing the emails, phone numbers, and the pages they came from.
What You’ll Need
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- Google Sheets for the input list and output file.
- Apify to extract emails, phones, and sources.
- Apify API token (get it from Apify Console → Settings → Integrations).
Skill level: Beginner. You’ll connect accounts, paste a Google Sheet URL, and run a test execution.
Don’t want to set this up yourself? Talk to an automation expert (free 15-minute consultation).
How It Works
You trigger it manually. Run the workflow when your “websites” sheet is ready, so you stay in control of when credits are used and when the output is created.
It grabs the sheet details and creates an output tab. You set the Google Sheet URL and the original sheet name once, then the workflow generates a fresh destination for the enriched results.
Apify does the crawling and extraction. n8n prepares the payload and starts the Apify Email & Phone Extractor actor, then pulls the dataset back when the run is done (this part can take a while on big sites).
Contacts get appended back into Google Sheets. The final step writes emails, phone numbers, and source pages into the new sheet so you can filter, dedupe, and start outreach.
You can easily modify the output columns to match your CRM import format based on your needs. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Manual Trigger
Set up the manual trigger so you can run the workflow on demand while testing.
- Add and open Manual Launch Trigger.
- No fields are required; keep defaults and save.
Step 2: Connect Google Sheets
Define the source sheet and create the output sheet in parallel.
- Open Assign Sheet Source Info and set google_sheet_url to
xxxxxxxxxxxx. - In the same node, set google_sheet_name to
websites. - Open Generate Output Sheet and set Operation to
create. - Set Title to
=emails-phones-{{new Date().format('dd/mm-HH:mm')}}and Document ID to={{ $json.google_sheet_url }}. - Credential Required: Connect your googleSheetsOAuth2Api credentials in Generate Output Sheet.
- Open Fetch Website List and set Sheet Name to
={{ $json.google_sheet_name }}and Document ID to={{ $json.google_sheet_url }}. - Credential Required: Connect your googleSheetsOAuth2Api credentials in Fetch Website List.
- Assign Sheet Source Info outputs to both Generate Output Sheet and Fetch Website List in parallel.
url or website, as Prepare Apify Payload reads from those fields.Step 3: Synchronize and Build the Apify Payload
Merge the parallel branches and construct the input payload for the Apify actor.
- Ensure Generate Output Sheet and Fetch Website List both connect to Synchronize Branches.
- Open Prepare Apify Payload and keep the JavaScript Code as provided, including the loop that reads Fetch Website List using
$('Fetch Website List').all().
Step 4: Configure Apify Execution and Dataset Retrieval
Run the Apify actor and pull the resulting dataset for enrichment.
- Open Execute Apify Actor and set Actor Source to
store. - Set Custom Body to
={{ $json }}. - Credential Required: Connect your apifyApi credentials in Execute Apify Actor.
- Open Retrieve Apify Dataset and set Resource to
Datasetsand Dataset ID to={{ $json.defaultDatasetId }}. - Credential Required: Connect your apifyApi credentials in Retrieve Apify Dataset.
Step 5: Configure Output to Google Sheets
Append the extracted contact data to the output sheet created earlier.
- Open Append Contacts to Sheet and set Operation to
append. - Set Sheet Name to
={{ $('Generate Output Sheet').first().json.sheetId }}. - Set Document ID to
={{ $('Assign Sheet Source Info').first().json.google_sheet_url }}. - Leave Columns in auto-map mode to map Apify fields to the sheet columns.
- Credential Required: Connect your googleSheetsOAuth2Api credentials in Append Contacts to Sheet.
Step 6: Test and Activate Your Workflow
Run a manual test to confirm the workflow creates a new sheet and appends enriched contacts.
- Click Execute Workflow from Manual Launch Trigger.
- Verify a new sheet is created with a title like
emails-phones-{{new Date().format('dd/mm-HH:mm')}}. - Check that Append Contacts to Sheet writes rows into the newly created sheet.
- Once confirmed, toggle the workflow to Active for production use.
Common Gotchas
- Google Sheets credentials can expire or lack write permissions. If rows don’t append, check the connected account access and the spreadsheet sharing settings first.
- If you’re using Wait nodes or external rendering, processing times vary. Bump up the wait duration if downstream nodes fail on empty responses.
- Apify runs can be slow on websites with lots of pages, and the actor can hit limits depending on your plan. Check the Apify run logs to confirm it’s still crawling, not stuck.
Frequently Asked Questions
About 30 minutes if your Google Sheets and Apify accounts are ready.
No. You’ll mainly connect credentials and update the Google Sheet URL and tab name.
Yes. n8n has a free self-hosted option and a free trial on n8n Cloud. Cloud plans start at $20/month for higher volume. You’ll also need to factor in Apify usage costs based on how many sites and pages you scan.
Two options: n8n Cloud (managed, easiest setup) or self-hosting on a VPS. For self-hosting, Hostinger VPS is affordable and handles n8n well. Self-hosting gives you unlimited executions but requires basic server management.
Yes, but it depends on how you want the final sheet to look. You can keep the Apify extraction the same and simply remove phone-related columns in the “Append Contacts to Sheet” mapping, which is the quickest approach. If you want to reduce what gets collected, adjust the configuration you send in “Prepare Apify Payload” so the actor focuses on the fields you care about. Most teams also customize the output to include a lead status column and a notes field for manual review.
Usually it’s an expired or incorrect Apify API token. Regenerate the token in your Apify account and update the Apify credentials in n8n, then rerun the workflow. If it still fails, check the Apify run page logs for permission issues with the actor or plan limits, and confirm the actor name/config matches what the workflow expects.
Practically, hundreds per run for most small teams, but the real limit is Apify crawl time and your n8n execution capacity. On n8n Cloud Starter, you’re capped by monthly executions; higher plans handle more. If you self-host, there’s no execution limit, so it mostly comes down to your server and how long each website takes to scan.
Often, yes. This workflow needs multi-step control: creating an output sheet, starting an Apify actor run, waiting for completion, then pulling a dataset and appending rows. n8n handles that kind of “long-running job + retrieval” flow more comfortably, and self-hosting can keep costs stable when you scale. Zapier or Make can still work, but you may end up juggling delays, polling steps, and task usage. If you’re unsure, Talk to an automation expert and you’ll get a straight recommendation.
Once this is running, your “research” step becomes a simple spreadsheet update and a single execution in n8n. Honestly, that’s a much better use of your time than opening 80 browser tabs.
Need Help Setting This Up?
Our automation experts can build and customize this workflow for your specific needs. Free 15-minute consultation—no commitment required.