Apify to Google Sheets, Upwork leads ready to pitch
Copying Upwork job links into a tracker, skimming descriptions, then writing “custom” proposals on a deadline is the kind of work that quietly drains your week. You miss good leads, reply too late, or send something generic because you’re rushing.
Upwork proposal automation hits freelancers hardest, honestly. But agency owners and small biz dev teams feel it too. The outcome is simple: new jobs get captured automatically, and you open a sheet full of ready-to-review drafts instead of starting from zero.
This workflow uses Apify + Google Sheets + AI to find matching Upwork jobs, avoid duplicates, and generate tailored proposals based on your own knowledge base. You’ll see how it works, what you need, and where teams usually trip up.
How This Automation Works
The full n8n workflow, from trigger to final output:
n8n Workflow Template: Apify to Google Sheets, Upwork leads ready to pitch
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-horizontal", form: "rounded", label: "Run Upwork Actor for Listed ..", pos: "b", h: 48 }
n2@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Get the Dataset from Upwork ..", pos: "b", h: 48 }
n3@{ icon: "mdi:database", form: "rounded", label: "Add the Extracted Data in Sh..", pos: "b", h: 48 }
n4@{ icon: "mdi:cog", form: "rounded", label: "Count the New Jobs", pos: "b", h: 48 }
n5@{ icon: "mdi:message-outline", form: "rounded", label: "Send Email Notification", pos: "b", h: 48 }
n6@{ icon: "mdi:swap-horizontal", form: "rounded", label: "If", pos: "b", h: 48 }
n7@{ icon: "mdi:brain", form: "rounded", label: "Google Gemini Chat Model", pos: "b", h: 48 }
n8@{ icon: "mdi:robot", form: "rounded", label: "Structured Output Parser", pos: "b", h: 48 }
n9@{ icon: "mdi:database", form: "rounded", label: "Get row(s) in sheet", pos: "b", h: 48 }
n10@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields", pos: "b", h: 48 }
n11@{ icon: "mdi:message-outline", form: "rounded", label: "Send a message", pos: "b", h: 48 }
n12@{ icon: "mdi:cog", form: "rounded", label: "Summarize", pos: "b", h: 48 }
n13@{ icon: "mdi:database", form: "rounded", label: "Append or update row in sheet", pos: "b", h: 48 }
n14@{ icon: "mdi:robot", form: "rounded", label: "Proposal Crafting", pos: "b", h: 48 }
n6 --> n14
n12 --> n11
n10 --> n13
n14 --> n10
n4 --> n5
n9 --> n6
n5 --> n9
n7 -.-> n14
n8 -.-> n14
n13 --> n12
n3 --> n4
n1 --> n2
n2 --> n3
n0 --> n1
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 n8,n14 ai
class n7 aiModel
class n1,n2,n6 decision
class n3,n9,n13 database
The Problem: Upwork outreach is repetitive (and easy to mess up)
Finding good Upwork jobs is not the hard part. The hard part is doing it consistently without turning your day into a loop of search, open tabs, copy/paste, and “I’ll write the proposal later.” Then later comes, and you’re rewriting the same structure again, trying to sound fresh while still answering client questions and proving fit. One skipped detail (budget, deadline, a specific tool mention) and your proposal reads like everyone else’s. The cost isn’t just time. It’s the mental drag that makes you avoid outreach in the first place.
It adds up fast. Here’s where it breaks down in real life:
- Manually tracking jobs in a spreadsheet usually takes about 5–10 minutes per job, and that’s before you’ve written a single sentence.
- Duplicates sneak in when you search multiple times a day, which means you waste effort pitching the same listing twice or second-guessing yourself.
- Proposals get “templated” because you’re tired, so you lose the personalization that actually wins replies.
- There’s no clean handoff for review, so you end up drafting in one place and submitting in another with extra copy/paste errors.
The Solution: Apify + Sheets + AI drafts proposals for every new job
This workflow acts like a small outreach assistant that never forgets steps. You start it manually in n8n, and it runs an Apify actor that scrapes Upwork based on criteria you choose (keywords, categories, verified payment status, and more). Each new job gets added to a Google Sheet so you have one tracking dashboard. Then the workflow reads the sheet back, checks which jobs have not been applied for, and triggers an AI proposal generator for each one. The AI uses the job details plus a built-in “Company Knowledge Base” section you customize, so the draft sounds like you (and references the right experience). Finally, it writes the proposal back into the same row and emails you a link so you can review and submit on Upwork.
The workflow begins with Apify pulling fresh listings. Google Sheets becomes the source of truth. From there, AI generates a tailored draft, and Gmail notifies you when everything is ready for review.
What You Get: Automation vs. Results
| What This Workflow Automates | Results You’ll Get |
|---|---|
|
|
Example: What This Looks Like
Say you target 10 solid Upwork jobs per day. Manually, you might spend about 10 minutes to log and de-duplicate each one (around 100 minutes), then another 15 minutes drafting a tailored proposal (about 150 minutes). That’s roughly 4 hours a day. With this workflow, you run the scrape once, then review drafts in one sheet. Even if you spend 5 minutes polishing each proposal, you’re closer to 50 minutes total, plus whatever time the AI takes to generate in the background.
What You’ll Need
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- Apify to scrape Upwork jobs by criteria
- Google Sheets to store leads and proposal drafts
- Google Gemini API key (get it from Google Cloud with Vertex AI enabled)
- Gmail to send “new jobs” and “drafts ready” emails
Skill level: Intermediate. You’ll connect accounts, edit a few fields, and paste in your own knowledge base content.
Don’t want to set this up yourself? Talk to an automation expert (free 15-minute consultation).
How It Works
Manual launch trigger. You click execute in n8n when you want to pull fresh jobs. Some teams run it once in the morning and once after lunch.
Job scraping and capture. Apify runs the Upwork scraping actor, then n8n fetches the dataset results and appends each job into Google Sheets with the important fields (title, URL, description, skills, questions).
Filter out leads you’ve already touched. The workflow reads the sheet rows and checks an “Applied” field. If it’s already marked, it skips proposal generation. Simple, but it saves you from accidental duplicates.
AI proposal drafting + saving. For every unapplied job, the AI agent uses the job details and your “Company Knowledge Base” to draft a relevant proposal, then writes it back into the same row. Gmail sends a final message with the link so you can review and submit.
You can easily modify the scraping criteria to focus on different niches 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 run it on demand while you finalize data sources and AI settings.
- Add and select Manual Launch Trigger as the starting node.
- Connect Manual Launch Trigger to Execute Upwork Actor to match the workflow flow.
Step 2: Connect Apify and Google Sheets
This section pulls Upwork data via Apify and stores it in Google Sheets for downstream processing.
- Open Execute Upwork Actor and connect it to Fetch Actor Dataset as shown in the execution flow.
- Credential Required: Connect your Apify credentials in Execute Upwork Actor and Fetch Actor Dataset.
- Open Append Data to Spreadsheet and configure it to append the dataset output into your target sheet.
- Credential Required: Connect your Google Sheets credentials in Append Data to Spreadsheet, Retrieve Sheet Rows, and Upsert Sheet Row.
- Verify the flow continues from Append Data to Spreadsheet to Tally New Listings.
Step 3: Configure Data Summaries and Conditional Logic
This middle layer tallies new listings, notifies you, and routes items for proposal drafting.
- In Tally New Listings, define how you want new records summarized before alerts go out.
- Configure Dispatch Email Alert to send a summary email after Tally New Listings.
- Credential Required: Connect your Gmail credentials in Dispatch Email Alert and Send Proposal Email.
- Set Retrieve Sheet Rows to read the necessary rows for proposal evaluation.
- Define the filtering logic in Conditional Check to decide which rows move into Proposal Drafting.
Step 4: Set Up the AI Proposal Drafting Chain
The AI chain generates proposals and structures the output for storage and email delivery.
- Open Proposal Drafting and verify it is connected to Gemini Chat Engine as its language model.
- Credential Required: Connect your Google Gemini credentials in Gemini Chat Engine.
- Ensure Structured Output Decode is connected to Proposal Drafting as the output parser.
- Note that Structured Output Decode is a sub-node—credentials are added to Gemini Chat Engine, not to the parser itself.
- Verify the flow from Proposal Drafting to Map Field Values so AI outputs are prepared for database updates.
Step 5: Configure Sheet Updates and Final Email Output
These nodes update your tracking sheet and deliver finalized proposals by email.
- In Map Field Values, map the proposal fields from the AI output into sheet columns.
- Set up Upsert Sheet Row to update or insert rows based on your chosen key.
- Confirm the flow from Upsert Sheet Row to Summarize Results and then to Send Proposal Email.
- Configure Send Proposal Email to send the proposal content from Summarize Results.
Step 6: Test and Activate Your Workflow
Run a manual test to validate each stage, then activate the workflow for ongoing use.
- Click Execute Workflow on Manual Launch Trigger to run a full test.
- Successful execution should show data appended in Append Data to Spreadsheet, AI output in Proposal Drafting, and a sent message from Send Proposal Email.
- If any node errors, verify credentials and input mappings before retesting.
- When ready for production, toggle the workflow to Active.
Common Gotchas
- Google Sheets credentials can expire or need specific permissions. If things break, check the n8n credential connection test and make sure the Sheet is shared with the right Google account 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.
- Default prompts in AI nodes are generic. Add your brand voice early or you’ll be editing outputs forever.
Frequently Asked Questions
About 45 minutes if your Apify, Sheets, and AI accounts are ready.
No. You’ll mostly connect accounts and edit the scraping filters plus the knowledge base prompt.
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 credits and Gemini API usage in Google Cloud.
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, and you should. Update the Apify “Run Upwork Actor” search parameters to match your niche, then rewrite the “Company Knowledge Base” section inside the Proposal Drafting prompt so the AI pulls from your real services, case studies, and preferred timeline.
Most of the time it’s an expired Google login or the sheet changed (new tab name, new document ID, or missing sharing permissions). Reconnect the Google Sheets credential in n8n, then confirm the Document ID and Sheet Name match what the nodes expect. If it still fails, check if your Google Workspace security settings require re-authorization more often than personal Gmail accounts.
Practically, dozens to a few hundred jobs per run, depending on your Apify limits and how much AI generation you’re comfortable paying for.
Often, yes, because this flow needs scraping + conditional logic + an AI chain that writes back to the same row. n8n handles branching and data mapping cleanly, and self-hosting avoids per-task pricing when volume increases. Zapier and Make can work, but you may end up stitching together more steps and paying more as you scale. If you’re only drafting a couple proposals a week, the simplicity of a lighter tool might be enough. Talk to an automation expert if you want a quick recommendation based on your volume.
Once this is running, your outreach stops depending on motivation and free time. The workflow handles the repeatable parts, and you show up to review and send.
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.