Apify to Google Sheets, clean leads ready to use
You run a scraper, download a file, open it, fix the columns, clean the phone numbers, normalize the emails… and then you still don’t trust the list. It’s tedious. Worse, it’s easy to miss a small formatting issue that wrecks your outreach later.
This is what sales reps feel right before a prospecting sprint. A marketing manager building a new list feels it too. So does an agency operator trying to deliver “clean leads” to a client. This Apify Sheets automation takes scraped results and drops them into Google Sheets already cleaned, so you can start outreach instead of babysitting exports.
Below you’ll see how the workflow runs, what it fixes automatically, and what “ready to use” actually means in a real weekly lead-gen routine.
How This Automation Works
The full n8n workflow, from trigger to final output:
n8n Workflow Template: Apify to Google Sheets, clean leads ready to use
flowchart LR
subgraph sg0["Flow 1"]
direction LR
n1["<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/httprequest.dark.svg' width='40' height='40' /></div><br/>Run Apify Scraper"]
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/code.svg' width='40' height='40' /></div><br/>Clean Data"]
n3@{ icon: "mdi:database", form: "rounded", label: "Export to Google Sheets", pos: "b", h: 48 }
n4@{ icon: "mdi:swap-vertical", form: "rounded", label: "Variables", pos: "b", h: 48 }
n4 --> n1
n2 --> n3
n1 --> n2
end
subgraph sg1["Manual Flow"]
direction LR
n0@{ icon: "mdi:play-circle", form: "rounded", label: "Manual Trigger", pos: "b", h: 48 }
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 n3 database
class n1 api
class n2 code
classDef customIcon fill:none,stroke:none
class n1,n2 customIcon
The Problem: Scraped Leads Are Never “Ready”
Scraping leads is the easy part. The painful part is everything after. You end up with phone numbers that include spaces, brackets, country codes in random formats, or even text mixed in. Emails come in with odd casing, trailing spaces, and duplicates you don’t spot until your bounce rate spikes. Then there’s the classic Google Sheets mess: columns shift, fields don’t match your outreach template, and someone on the team “quickly fixes it” in a way nobody can repeat next time. Honestly, it’s not the work you remember to track, but it costs you real hours.
The friction compounds. Here’s where it usually breaks down.
- Exporting from Apify, re-uploading, and mapping columns burns about 30 minutes per scrape.
- Phone and email formatting inconsistencies create preventable bounces and failed dial attempts.
- You lose momentum because outreach can’t start until someone “cleans the sheet.”
- Each manual cleanup is slightly different, which makes list quality unpredictable week to week.
The Solution: Run Apify, Normalize the Data, Append to Sheets
This workflow turns “scraped dataset” into a consistent Google Sheet you can actually use. You trigger it in n8n, it loads your Apify credentials (token and task ID), then launches the Apify task via an HTTP request. When the results come back, the workflow normalizes the fields you care about for outreach. Phone numbers get stripped down to digits so they behave in dialers and CRMs. Emails are trimmed and lowercased, which reduces duplicates and prevents silly copy-paste errors later. Finally, the cleaned rows are appended to your Google Sheet, with predictable columns like company name, phone, and address.
The workflow starts with a manual launch, so you can run it on demand when you need fresh leads. From there, Apify does the scraping, n8n cleans the output, and Google Sheets becomes your single source of truth. No extra downloads. No “which version of the CSV is this?” conversations.
What You Get: Automation vs. Results
| What This Workflow Automates | Results You’ll Get |
|---|---|
|
|
Example: What This Looks Like
Say you scrape 300 leads every Monday and Thursday. Manually, you might spend about 30 minutes exporting and reformatting the file, then another 30 minutes cleaning phones, emails, and column names, so call it 2 hours a week. With this workflow, you click run, wait for Apify to finish (often around 10 minutes), and your Google Sheet is updated automatically. That’s roughly 90 minutes back weekly, plus fewer mistakes when you hand the list to someone else.
What You’ll Need
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- Apify for running your lead scraping task
- Google Sheets to store and share cleaned lead rows
- Apify API token (get it from Apify Console → Settings → Integrations)
Skill level: Beginner. You’ll paste credentials, pick your spreadsheet, and run a test scrape.
Don’t want to set this up yourself? Talk to an automation expert (free 15-minute consultation).
How It Works
Manual launch from n8n. You trigger the workflow when you want fresh leads, which is useful if you scrape on specific days or only when a campaign needs it.
Credentials and task details are loaded. n8n reads your APIFY_TOKEN and APIFY_TASK_ID from the variables step so the workflow can run the right Apify scraper without you reconfiguring anything.
Apify runs and returns the dataset. An HTTP request launches the scrape and pulls the results back into n8n, so you can process the data before it ever touches your sheet.
Lead data is normalized and appended. The cleanup logic standardizes phones and emails, then the Google Sheets step appends new rows to your chosen spreadsheet in a consistent column order.
You can easily modify the cleanup rules to match your CRM requirements based on your needs. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Manual Trigger
This workflow starts manually so you can test the Apify scrape and sheet append on demand.
- Add the Manual Launch Trigger node as the workflow trigger.
- Leave the default settings as-is since this node does not require configuration.
- Connect Manual Launch Trigger to Assign Workflow Vars to follow the execution flow.
Step 2: Connect the Apify Request
Set your Apify credentials as variables and build the API request URL dynamically.
- Open Assign Workflow Vars and set APIFY_TOKEN to
[CONFIGURE_YOUR_API_KEY]. - Set APIFY_TASK_ID to
[YOUR_ID]. - In Execute Apify Scrape, set URL to
{{ 'https://api.apify.com/v2/actor-tasks/' + $json.APIFY_TASK_ID + '/run-sync-get-dataset-items?token=' +$json.APIFY_TOKEN}}. - In Execute Apify Scrape enable Options → Split Into Items so each dataset row becomes an individual item.
- Connect Assign Workflow Vars → Execute Apify Scrape.
Step 3: Set Up Lead Data Normalization
The code step cleans phone numbers and normalizes email addresses before storing the lead data.
- Add the Normalize Lead Data node after Execute Apify Scrape.
- Paste the JavaScript in Normalize Lead Data exactly as shown:
// Clean scraped data before LLM processing return $input.all().map(item => ({ ...item.json, phone: item.json.phone?.replace(/[^\d+]/g, '') || '', email: item.json.email?.toLowerCase().trim() || '' })); - Connect Execute Apify Scrape → Normalize Lead Data.
Step 4: Configure the Output Destination
Append the normalized lead data into Google Sheets using defined column mappings.
- Add the Append to Sheets node and connect it to Normalize Lead Data.
- Credential Required: Connect your Google Sheets credentials in Append to Sheets.
- Set Operation to
append. - Set Document ID to
[YOUR_ID]. - Set Sheet Name to
Sheet1. - Map columns in Columns → Define Below:
- phone →
{{ $json.phone }} - Address →
{{ $json.address }} - company name →
{{ $json.title }}
- phone →
Step 5: Test and Activate Your Workflow
Run a manual test to verify the scrape and append behavior, then activate the workflow for use.
- Click Execute Workflow to run Manual Launch Trigger.
- Confirm Execute Apify Scrape returns items and Normalize Lead Data outputs cleaned phone and email fields.
- Verify new rows appear in the target Google Sheet from Append to Sheets.
- When successful, toggle the workflow to Active for production use.
Common Gotchas
- Apify credentials can expire or your token can lose permissions. If things break, check your token status in the Apify Console and confirm the task ID still exists.
- If you’re using Wait nodes or external rendering, processing times vary. Bump up the wait duration if downstream nodes fail on empty responses.
- Default prompts in AI nodes are generic. Add your brand voice early or you’ll be editing outputs forever.
Frequently Asked Questions
About 20 minutes if you already have an Apify task and a Google Sheet ready.
No. You’ll paste your Apify token and task ID, then select the target Google Sheet. The data cleanup is already built into the workflow.
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 often your task runs.
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 you’ll want to do it intentionally. You can adjust the field mapping in the “Append to Sheets” step to match your CRM column names, and you can tweak the cleanup rules in “Normalize Lead Data” to handle country codes, required prefixes, or extra fields like website and category. Common customizations include adding a “source” column, splitting addresses into city/state, and skipping rows that don’t have a valid email.
Most of the time it’s a token issue or the task ID is wrong. Regenerate your APIFY_TOKEN in Apify, confirm the APIFY_TASK_ID matches the task you expect, then update the variables in n8n. If it fails only on big scrapes, you may also be hitting rate limits or returning a dataset that takes longer to generate than your request expects.
Hundreds per run is normal, and thousands are fine if your Apify task can produce them reliably.
Often, yes, because scraping outputs tend to need real cleanup logic before they’re useful. n8n makes that kind of data shaping easier to maintain, and self-hosting means you’re not paying extra every time you run a bigger batch. Zapier and Make can still work if you’re doing a simple “send data to sheet” flow, but they get awkward when you need conditional rules and repeatable normalization. If your workflow will grow, n8n is usually the calmer choice. Talk to an automation expert if you want a quick recommendation for your setup.
Clean leads showing up in Sheets without the cleanup ritual changes the pace of your week. Set it up once, run it when you need it, and keep your outreach moving.
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.