ZipRecruiter Scraper - Jobs, Salaries & Companies
Pricing
from $1.00 / 1,000 results
ZipRecruiter Scraper - Jobs, Salaries & Companies
From $1/1K. Scrape ZipRecruiter jobs with titles, companies, salaries, locations, benefits, apply URLs and full descriptions. Search with filters or paste ZipRecruiter URLs directly, with automatic pagination and simple pay-per-result pricing.
Pricing
from $1.00 / 1,000 results
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
0
Bookmarked
6
Total users
1
Monthly active users
7 days ago
Last modified
Categories
Share
ZipRecruiter Scraper: Job Titles, Parsed Salary, Location & Apply Links
ZipRecruiter Scraper turns ziprecruiter.com job search into structured data. Get title, company, company logo, parsed salary (min, max, period), structured location, employment type, benefits, posted date and an apply link for every listing. Build a search from keywords and filters, or paste any ziprecruiter.com search or job URL straight from your browser, then export to JSON, CSV or Excel, or read the results through the API.
Why This Scraper?
- Two ways to find listings. Build a search from keywords, location and filters, or paste finished ziprecruiter.com search or job URLs (multiple supported, each pages forward on its own).
- About 50 fields per record, around 35 filled from the search results alone. Parsed salary (min, max, period), structured location (city, state, county), employment type, company logo and an apply URL ship without opening a detail page; company website, full address, coordinates, industry, benefits text and the full description need Fetch full listing details.
- Optional detail mode for the long form. Switch it on for the full description text, a structured street address, industry, valid-through date, verified salary, and any contact email or phone number the employer pasted into the listing.
- Filters that apply to the search and the results. Date posted, employment type, remote-only, minimum salary and search radius.
- Forward pagination with de-duplication. The actor reads the site's own result-count to know when a search ends, and never saves the same job id twice.
- Continue a large pull across separate runs. Point
resumeFromRunIdat a previous run or dataset and only the listings not already collected there are saved (and billed). - Resilient to a refused request. The actor automatically opens a fresh connection and retries when one request is refused, so a single blocked page does not sink the whole run.
Use Cases
- Job board aggregation: build or refresh your own jobs feed with structured salary, location and employment-type data.
- Recruiting and sourcing: pull open roles by keyword and location to find which companies are hiring for a given skill set.
- Labor market and salary research: collect parsed salary ranges across roles, regions and employment types for benchmarking.
- Competitor and hiring-trend tracking: monitor which roles a company is posting and how its listings change over time.
- New-listing alerting: watch a keyword or location and use
resumeFromRunIdto skip jobs already collected in that specific run or dataset. - Data science and NLP: build a labeled dataset of job titles, descriptions and requirements for classification or matching models.
Data You Get
Sample shape: values are illustrative placeholders, not from a live record.
| Field | Example |
|---|---|
id | "ad8a4fef327eab36" |
title | "Full Stack Software Engineer" |
company | "Sample Employer Inc" |
companyWebsite | "sampleemployer.com" (detail mode only) |
companyLogo | "https://www.ziprecruiter.com/svc/fotomat/.../sample123.png" |
location / city / state | "Reston, VA" / "Reston" / "Virginia" |
county / country | "Fairfax" / "United States" |
locationType / remote | "On-site" / false |
salary | "$123K - $161K/yr" |
salaryMin | 123000 |
salaryMax | 161000 |
salaryPeriod / salaryCurrency | "year" / "USD" |
employmentType / employmentTypes | "FULL_TIME" / ["FULL_TIME"] |
benefits | ["MEDICAL", "LIFE_INSURANCE"] |
industry / occupationalCategory | "Technology" / "15-1133.00: Software Developers, Systems Software" (detail mode only) |
snippet | "THE IMPACT YOU WILL MAKE The Full Stack Software Engineer role will offer you..." |
descriptionText | full listing description text (detail mode only) |
emails / phoneNumbers | parsed from the listing text when an employer pasted one; usually empty |
datePosted / validThrough | "2026-04-24T00:00:00Z" / "2026-06-23" (validThrough is detail mode only) |
applyUrl | ziprecruiter.com link carrying the job's jid |
sponsored | false |
source / scrapedAt | "ZipRecruiter" / "2026-05-25T00:00:00.000Z" |
Fields marked "detail mode only" are populated only when Fetch detail pages is on. Every plain search-mode run still carries id, url, listingKey, title, company, location, salary, employmentTypes, benefits and snippet; emails and phoneNumbers are always present as arrays but are usually empty, since ZipRecruiter exposes no structured contact field.
How to Use
- Pick a mode:
search(build a query from keywords and filters) orurl(paste one or more ziprecruiter.com links). - For search mode, fill in keywords and location, then switch on any filters you need (date posted, employment type, remote-only, minimum salary, radius). For URL mode, paste your links; date posted and radius are ignored (they only shape the search URL), but employment type, remote-only and minimum salary still screen the results after they're fetched.
- Set Max pages per search and Max listings (total) to control run size and cost, and turn on Fetch detail pages if you need the full description.
- Click Start, then download the dataset as JSON, CSV or Excel, or read it through the API.
Basic keyword search:
{"mode": "search","queries": ["software engineer"],"location": "Remote","maxPages": 5,"fetchDetails": false}
Search with filters (full-time, posted in the last 5 days, minimum salary):
{"mode": "search","queries": ["registered nurse"],"location": "Chicago, IL","datePosted": "5","employmentType": "full_time","minSalary": 70000,"maxPages": 10,"fetchDetails": true}
Remote jobs only, multiple keywords:
{"mode": "search","queries": ["data analyst", "data engineer", "data scientist"],"remoteOnly": true,"maxPages": 5,"maxListings": 300}
Paste finished ziprecruiter.com URLs (URL mode):
{"mode": "url","urls": ["https://www.ziprecruiter.com/jobs-search?search=software+engineer&location=New+York%2C+NY","https://www.ziprecruiter.com/jobs-search?search=warehouse&location=Dallas%2C+TX&days=5"],"maxPages": 3}
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/ziprecruiter-com-scraper").call(run_input={"mode": "search", "queries": ["software engineer"], "location": "Remote"})for job in client.dataset(run["defaultDatasetId"]).iterate_items():print(job["title"], job["company"], job["salary"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/ziprecruiter-com-scraper').call({mode: 'search',queries: ['software engineer'],location: 'Remote',});const { items } = await client.dataset(run.defaultDatasetId).listItems();
Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.
Employment-type filtering
ZipRecruiter treats the employment-type filter loosely: it narrows the search but also backfills the results with related jobs, so a part-time search can still surface some full-time roles. This scraper passes your choice to the search and also screens the results so the output favors your requested type, but keeps jobs whose type ZipRecruiter did not label rather than dropping them, which keeps results flowing in thin markets. If you need an exact match only, filter the employmentTypes field in your downstream pipeline.
Caps and resuming a large pull
maxPagesandmaxListingscap a single run. LeavemaxPagesat0to walk every page ZipRecruiter serves for a search, bounded only bymaxListingsand the site's own result total.resumeFromRunIdcontinues a pull across separate runs: paste a previous run's ID (or its dataset ID), and this run loads every job id already saved there and appends only the ones it hasn't seen.- If a run is interrupted by an Apify platform migration, or you click Resurrect on a failed run, it picks back up automatically in the same run without re-saving, or re-charging for, listings it already collected. No input is needed for this.
Send results into your apps (MCP connectors)
Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.
What gets written to the connector: a condensed, human-readable summary of each record, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.
- Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
- For Notion, also set
notionParentPageUrlto the page where items should be created.
The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | string | search | search builds a query from the fields below; url reads from urls. |
queries | array | none (prefill: ["software engineer"]) | Keywords. One scrape per keyword. Empty browses without a keyword filter. |
location | string | none (prefill: "Remote") | City and state, ZIP, or "Remote". Left empty, the search runs nationwide. |
datePosted | string | any | any, 1, 5, 10, or 30 days. |
employmentType | string | any | any, full_time, part_time, contract, temporary, internship. |
remoteOnly | boolean | false | Only return jobs flagged remote. |
minSalary | integer | 0 | Minimum advertised annual salary. 0 = no floor. |
radius | integer | 0 | Search radius in miles around the location. 0 = site default. |
skipSponsored | boolean | false | Drop sponsored placements (applied client-side). |
urls | array | none (prefill: a sample search URL) | URL mode: one or more ziprecruiter.com search or job URLs. |
maxPages | integer | 0 | Result pages to walk per search or URL (about 20 listings each). 0 = unlimited: walk every page ZipRecruiter serves for that search. |
maxListings | integer | 20 | Total listings cap across all searches. 0 = no cap (still bounded by maxPages). |
fetchDetails | boolean | false | Also open each job page for the full description, structured address, industry, valid-through date and verified salary. |
resumeFromRunId | string | none | A previous run ID or dataset ID to continue a large pull across separate runs. Listings already collected there (matched by job id) are skipped. |
proxy | object | none in the schema (prefill: Apify Proxy, RESIDENTIAL group, country US); when this field is left out entirely, the actor applies that same residential US routing automatically | Connection settings. A residential connection is required; see Plan Requirement below. |
mcpConnectors | array | none | Optional: send a summary of each record to apps you authorized under Integrations. |
notionParentPageUrl | string | none | Notion connector only: page under which records are created. |
maxNotifyListings | integer | 50 | Cap on items written to each connector per run. Does not affect the dataset. |
Output Example
Sample shape: values are illustrative placeholders, not from a live record.
{"id": "ad8a4fef327eab36","listingKey": "sample-listing-key","url": "https://www.ziprecruiter.com/c/Sample-Employer-Inc/Job/Full-Stack-Software-Engineer/-in-Reston,VA?jid=ad8a4fef327eab36","title": "Full Stack Software Engineer","company": "Sample Employer Inc","companyWebsite": "sampleemployer.com","companyLogo": "https://www.ziprecruiter.com/svc/fotomat/public-nosensitive-ziprecruiter-logos/company/sample123.png","location": "Reston, VA","city": "Reston","state": "Virginia","county": "Fairfax","postalCode": "20190","streetAddress": "1100 Sample Way","country": "United States","locationType": "On-site","remote": false,"salary": "$123K - $161K/yr","salaryMin": 123000,"salaryMax": 161000,"salaryCurrency": "USD","salaryPeriod": "year","employmentTypes": ["FULL_TIME"],"employmentType": "FULL_TIME","industry": "Technology","occupationalCategory": "15-1133.00: Software Developers, Systems Software","benefits": ["MEDICAL", "LIFE_INSURANCE"],"snippet": "THE IMPACT YOU WILL MAKE The Full Stack Software Engineer role will offer you the flexibility to make each day your own...","descriptionText": "Full job description text appears here when Fetch detail pages is on.","emails": [],"phoneNumbers": [],"datePosted": "2026-04-24T00:00:00Z","validThrough": "2026-06-23","isActive": true,"directApply": true,"applyUrl": "https://www.ziprecruiter.com/c/Sample-Employer-Inc/Job/Full-Stack-Software-Engineer/-in-Reston,VA?jid=ad8a4fef327eab36","sponsored": false,"searchQuery": "software engineer","searchLocation": "Remote","pageNumber": 1,"source": "ZipRecruiter","scrapedAt": "2026-05-25T12:00:00.000Z"}
Plan Requirement
ZipRecruiter requires a residential connection; a datacenter connection is rejected outright. The default proxy setting already routes through a residential connection pinned to the United States, so it works out of the box, and the actor automatically opens a fresh connection and retries when one is refused. If you supply your own proxy configuration instead of the default, make sure it also routes through a residential US connection, since a non-residential one will not return data.
FAQ
How much does it cost?
You pay per listing returned, and detail-mode enrichment may add a per-item surcharge when it's switched on. The Pricing tab on the actor page shows the current rates. Use Max listings and Max pages per search to cap the size, and therefore the cost, of any run.
Is it legal to scrape ZipRecruiter?
This actor collects only publicly available job listing data. You are responsible for how you use it: follow ZipRecruiter's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Job descriptions, company logos and photos may carry their own copyright or trademark protections even though the listing itself is public.
Can I get only new listings on a schedule?
There is no automatic new-only mode. Instead, paste a previous run's ID (or its dataset ID) into resumeFromRunId: the actor loads every job id already saved in that one run or dataset and appends only listings it hasn't seen there. It does not dedupe against everything you've ever collected, only against the single run or dataset you point it at. Because Apify Schedules run with a fixed input, keeping this fully automatic on a schedule means updating resumeFromRunId to the latest run's ID before each new run, typically by driving runs through the API instead of a static schedule, or deduping downstream on id across every run's output.
Why does a search return jobs that don't match my employment-type filter?
ZipRecruiter's own employment-type filter is loose: it narrows the search but also backfills the results with related jobs, so a part-time search can still surface full-time roles. This actor enforces your choice on top of the site's own filtering, but keeps jobs whose type the site left unlabeled rather than dropping them, so thin markets still return results. See "Employment-type filtering" above for how to enforce an exact match downstream.
Why did my run fail instead of returning an empty dataset?
Two situations end the run outright: no proxy configuration could be resolved when the run starts, or resumeFromRunId points at a run or dataset your Apify account can't read (checked before any scraping starts, so a bad ID doesn't burn a search). Every other failure, such as one search's connection being repeatedly refused, only ends that one search early; the run itself still completes and keeps any listings already collected.
Why did a run complete but return zero listings?
Confirm your keywords and location match a real ZipRecruiter search in your own browser, or try URL mode with a link pasted straight from the site. Also confirm your proxy configuration routes through a residential US connection, since ZipRecruiter rejects most other traffic.
Can I use it with AI agents or MCP?
Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.
🔗 Want more jobs data?
Pair this actor with these related scrapers from the same team:
| 💼 CareerBuilder Scraper Scrape CareerBuilder.com job listings by search or URL. Returns title, company profile... | 💼 Dice.com Scraper Scrape tech job listings from Dice.com by keyword, filters, or URL. Extract job titles... |
| 💼 Monster Jobs Scraper Scrape Monster.com job listings from search and direct job URLs. Extract full... | 💼 NIJobs Scraper Scrape NIJobs.com listings across Northern Ireland by keyword, location, salary, posted... |
| 💼 s1jobs Scraper Scrape jobs from s1jobs.com across Scotland and the UK. Search by keyword, location, or... | 💼 JobStreet From $1/1K. Scrape JobStreet listings across Malaysia, Singapore, Indonesia, and the... |
💬 Support & custom scrapers
- 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
- 🛠️ Need another site, extra fields or a private build? Email abotapi@proton.me or message Telegram @abotapi.
- ⭐ Enjoying it? A quick review on the actor page helps other users find it.