Choose the simplest route that fits
Use a manual export when you need a one-time spreadsheet. Use n8n when the same reviewed search should run repeatedly or another system needs the rows automatically.
| Need | Best route | Start here |
|---|---|---|
| One-time research file | Run in Apify, open the Dataset, and export CSV or Excel. | One role, one location, up to 25 rows. |
| Recurring spreadsheet | Save an Apify Task, run it from n8n, retrieve Dataset items, then update Google Sheets. | One-result Task before any schedule. |
| Known job URLs or IDs | Use Job Details for complete descriptions and criteria. | One current public job. |
| Role and location discovery | Use Jobs Search, then enrich selected IDs only when needed. | Ten search rows. |
Verify one job before connecting anything
Open the bounded one-job sample Task. It resolves a current public job at run time, so the guide does not depend on one old listing staying live.
{
"jobUrlsOrIds": [],
"starterSearchQuery": "data engineer",
"starterSearchLocation": "London",
"maxResults": 1
}
Open the Dataset and verify jobId, jobUrl, title, company, location, description, criteria, salary text, applicant text, and application path. Missing optional fields should remain empty. They should never be guessed.
Prepare a narrow Google Sheet
Create columns only for fields you will use. A practical first sheet includes:
| Column | Why keep it |
|---|---|
jobId | Stable key for duplicate checks and updates. |
jobUrl | Source link for human verification. |
title, company, location | Core job identity and filtering. |
description | Full public role context for search or analysis. |
salaryText, applicantCountText | Direct public evidence when available; otherwise blank. |
applicationType, applyUrl | Preserves the disclosed application path. |
scrapedAt | Shows when the source was observed. |
Download the starter files
Download the one-job starter ZIP. It contains a spreadsheet header template and an inactive n8n workflow under examples/. Import the JSON, add your own Header Auth credential privately, and inspect the single validated row before connecting a Google Sheets write.
This template calls the Actor directly; the saved-Task recipe below is an alternative. It requests one row, a $0.05 pay-per-event charge ceiling, and a 120-second Actor timeout. No tokens, customer data, schedules, or Sheets credentials are included. Offline checks pass, but live n8n import and Sheets delivery still need validation in your account.
Already have job IDs in a spreadsheet? The ZIP also includes src/run_job_batch.py. Export up to ten unique IDs into a single job_id CSV column, then follow the preview, execute, and resume walkthrough. It saves checked JSON rows locally; it does not write to Sheets. Inspect partial results and missing IDs before importing, and keep the run journal to avoid duplicate paid starts.
Build the n8n workflow
This section is an integration recipe, not a verified end-to-end Google Sheets deployment. The prepared Neuton starter stops at a Sheets-ready row; its offline checks do not prove an n8n import, a Google Sheets write, or a scheduled run. Validate those steps in your own accounts before relying on the automation.
- Add a Manual Trigger. Do not begin with a schedule.
- Create an Apify credential in n8n. Keep the token in n8n's credential store, never in a Sheet cell, node label, URL, screenshot, or workflow export.
- Add the Apify Run Task operation and select the reviewed one-job Task.
- Wait for a terminal run status. Continue only when the run is
SUCCEEDED. - Add Apify Get Dataset Items and map the run's
defaultDatasetId. - Add a Google Sheets lookup using
jobId, followed by append for new rows or update for existing rows. - Run the workflow manually and compare the Sheet row with the Apify Dataset and source URL.
Apify's official n8n integration guide documents the Actor, Task, trigger, and Dataset operations. Its Dataset guide explains exports and API retrieval.
The input is visible and reviewable in Apify. Several workflows can reuse it without copying a large JSON object into every automation.
Deduplicate by job ID before appending
Use jobId as the primary spreadsheet key. Look for that value before writing. Append when it is new; update the matching row when the same job is observed again. Do not deduplicate by title alone because different companies and locations can use the same title.
When using Jobs Search before Job Details, deduplicate the search output first and enrich only the unique IDs your workflow needs. This avoids paying for repeated detail rows.
Do not turn a failed run into a job-market event
A failed, timed-out, or incomplete run should stop the Sheet update and send an operational alert. It should not clear rows, mark jobs as removed, or create an empty daily snapshot. Open RUN_SUMMARY to distinguish expired inputs, incomplete public pages, and bounded source failures.
The Dataset is empty
Check the run status and RUN_SUMMARY. Try the current one-job starter to separate an expired URL from a broader source problem.
The same job appears twice
Confirm the Google Sheets lookup runs before append and compares the exact jobId as text.
The salary cell is blank
Many public job pages do not disclose salary. Keep the cell blank instead of filling an estimate.
Can I add profiles or recruiter emails?
No. This workflow is limited to public job postings and does not collect private profiles, employee directories, or personal contact data.
Control cost before scheduling
The live Apify Pricing tab is authoritative. Keep maxResults at 1 for the integration test, then increase one limit at a time. The Job Details Actor keeps skipped-input diagnostics outside its Dataset, but a saved row can still lack fields your workflow needs. Validate the row before writing to Sheets and inspect run charges separately; a result limit is not a complete spending cap.
After the manual workflow passes, replace Manual Trigger with a daily or weekly schedule. Keep the result limit bounded and review the first scheduled run before leaving it unattended.
Start with one row, not a full automation
Run the current sample, verify the complete public record, and connect the reviewed Task only when the row belongs in your Sheet.
