ZipRecruiter Scraper at a glance
ZipRecruiter Scraper is a ready-to-run Apify actor from abotapi for collecting jobs data. Its documented output includes id, url, title, company and logo, which you can export as JSON, CSV or Excel or read through the Apify API. It costs $1.70 per 1,000 results on the Apify Free plan and from $1.00 on paid plans, with smaller per-run or optional feature charges listed on Apify.
- Runs on
- Apify cloud: console, API, schedules and integrations
- Data type
- Jobs, Automation, Developer Tools
- Pricing
- $1.70 per 1,000 results (Free plan), from $1.00 on paid plans
- Output
- Documented below · JSON, CSV, Excel
- Inputs
- 28 options
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.
What ZipRecruiter Scraper can do
- 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 and maximum salary, workplace type, external-apply only 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 resumeFromRunId at a previous run or dataset and only the listings not already collected there are saved (and billed).
Choose what to collect
These inputs let you configure ZipRecruiter Scraper - Jobs, Salaries & Companies. Open the actor on Apify to enter your values and review the current options.
| Input | What it controls |
|---|---|
modestring · required | Search mode = pick keywords + location + filters below. URL mode = paste any ziprecruiter.com search or job URL refined in your browser. |
queriesarray | Free-text search terms (e.g. "software engineer", "registered nurse", "data analyst"). One scrape per keyword. Leave empty to browse without a keyword filter. |
locationstring | City + state, ZIP, or "Remote". Examples: "New York, NY", "Chicago, IL", "94103", "Remote". Leave empty to search nationwide. |
datePostedstring | Only return jobs posted within this window. "Any time" walks the unfiltered SERP. |
employmentTypestring | Filter by employment scope. "Any" walks the unfiltered SERP. |
remoteOnlyboolean | Only return jobs flagged as remote. |
minSalaryinteger | Only return jobs whose advertised pay is at or above this annual figure. Leave at 0 for no salary floor. |
Show 21 more inputs
| Input | What it controls |
|---|---|
radiusinteger | Distance around the location to include. Leave at 0 to use ZipRecruiter's default radius. |
skipSponsoredboolean | Drop sponsored / promoted job cards. Applied as a client-side filter. |
urlsarray | One or more ziprecruiter.com URLs. Supported: a search URL (…/jobs-search?search=software+engineer&location=Remote), a legacy keyword path (…/Jobs/Software-Engineer, mapped to a search), or a single job URL (…/c/Raytheon/Job/Software-Engineer-II-(Onsite)/-in-Tucson,AZ?jid=36f7f16aec6bade9). Multi-URL supported; each search URL pages forward independently. Remote and minimum-salary facets in a pasted URL are honoured. Leaving this field untouched in URL mode scrapes one example per shape. |
maxPagesinteger | How many SERP pages to walk per keyword × location combination (or per pasted URL). Each page returns up to 20 listings. Leave empty to walk every result page (bounded by maxListings and ZipRecruiter's own result total). |
maxListingsinteger | Stop after this many listings across all searches. 0 = no cap (still bounded by maxPages). |
fetchDetailsboolean | When ON, also fetch each job's detail page for the full HTML description, structured street address, industry, valid-through date, and verified salary. SERP cards already carry id, title, company, location, salary, employment type, benefits, snippet, and posted date, so most feeds work great with this OFF (faster and cheaper). Default OFF. |
maxItemsPerSearchinteger | Extra ceiling for each keyword or each pasted link, on top of the even share of Max listings. 0 = no extra ceiling. |
workplacestring | Keep only jobs the site tags as remote, hybrid or on-site. Applied to the loaded results, so a narrow choice can return fewer jobs than Max listings; the run is then not treated as a complete read of the search. 'On-site' also keeps jobs that carry no workplace tag. |
maxSalaryinteger | Drop jobs whose lowest advertised annual pay is above this figure. Only jobs paid per year are screened; hourly, weekly and unpriced jobs are kept. 0 = off. |
externalApplyOnlyboolean | Keep only jobs whose apply button leads to an external employer or partner page (externalApplyUrl is set). Applied to the loaded results. |
descriptionMaxLengthinteger | Cut descriptionText, description and descriptionMarkdown to this many characters. descriptionHtml is set to null when it is longer than the limit (a cut HTML string would be invalid). Does not change what counts as UPDATED. 0 = full text. |
omitEmptyFieldsboolean | Drop fields whose value is null, empty text or an empty list from each row, for a smaller dataset. Does not change what counts as UPDATED. |
resumeFromRunIdstring | Paste a previous run ID or dataset ID to continue a full-catalogue walk across separate runs. Listings already collected there (matched by job id) are skipped, so this run only saves the new ones. Leave empty for a normal fresh run. |
incrementalModeboolean | Turn this on for daily or recurring monitoring of the same search. The first run returns every matching job as NEW. Later runs return only NEW, UPDATED and REAPPEARED jobs; unchanged jobs are neither returned nor billed. Every returned row gets changeType, changedFields, firstSeenAt and lastSeenAt. A job counts as UPDATED when any field other than these ignored ones changed: scrapedAt, pageNumber, sponsored, inputUrl, postedAt, datePosted, listingKey, companyLogo (the scrape time, the results page the job landed on, the promoted flag, the start link, the posted time, the listing tracking key and the logo link change without any real change to the job). Everything else counts, for example title, salary, location, description, benefits, apply link, so a changed salary or description returns the job as UPDATED with the field names in changedFields. Ignored fields are still returned in each row. Add your own with the ignore list at the end of this section. State is kept per search (mode, queries, location, filters, detail setting, URLs), never per item limit or page limit. Use State key to name a campaign. To continue one interrupted run instead, use Resume from a previous run above. |
stateKeystring | Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently configured runs. Leave empty to derive a key from the search settings, so different searches never mix state. |
emitUnchangedboolean | Off by default. Turn on to also return jobs that have not changed since the last run, marked UNCHANGED. These rows are delivered and billed like any other row, so leave it off unless you want the full snapshot every run. |
emitExpiredboolean | Off by default. Turn on to also return jobs seen in a previous run that are no longer found, marked EXPIRED. Only produced after a run that read the whole search up to the last page the site reports: not when Max listings or Max pages stopped it, not for a pasted single job link or a link that starts after page 1, not when any filter (sponsored, salary, employment type) removed jobs, not with Resume, and not when a page or detail page failed. These rows are delivered and billed like any other row, and they count toward Max listings: any beyond it are reported on a later run. |
ignoreFieldsForChangesarray | Output field names that should NOT make a job count as UPDATED, even when they changed. Always ignored: scrapedAt, pageNumber, sponsored, inputUrl, postedAt, datePosted, listingKey, companyLogo (listed here so you know; you do not need to add them). A name without a dot matches that field at any nesting depth; a dotted name matches from the top of the row. Ignored fields are still returned in the output. |
mcpConnectorsarray | Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify → Settings → Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON, the complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com). |
notionParentPageUrlstring | URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors. |
maxNotifyListingsinteger | Cap on items written to each connector per run. Does not affect the dataset. |
Fields in the output
The documented dataset includes the fields below. Availability can depend on the source page and selected mode.
idIDurlURL (link)titleTitlecompanyCompanycompanyLogoLogo (image)cityCitystateStatelocationTypeSettingsalarySalarysalaryMinMin PaysalaryMaxMax PaysalaryPeriodPeriodShow 30 more fields
employmentTypesTypebenefitsBenefitsremoteRemotedatePostedPostedapplyUrlApply (link)snippetSnippetemailsEmailsphoneNumbersPhonessponsoredSponsoredscrapedAtScrapedworkplaceTypeWorkplaceisRemoteIs RemoteisExternalApplyExternal ApplycontactEmailContact EmailcontactWebsiteContact WebsitedescriptionMarkdownDescription (MD)detailsFetchedDetails FetcheddescriptionIncompleteDescription IncompleteinputUrlInput URL (link)descriptionTextDescriptiondescriptionHtmlDescription (HTML)industryIndustryoccupationalCategoryCategoryvalidThroughValid throughdirectApplyDirect applycompanyWebsiteCompany websitechangeTypeChangechangedFieldsChanged fieldsfirstSeenAtFirst seenlastSeenAtLast seenExample output
An example from this actor’s documentation. Values are illustrative; this is not a fresh live result.
{
"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"
}Ways to use this data
- 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 resumeFromRunId to 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.
Before you run
Start with a small input and check the resulting records against your expected fields. Source content and actor options can change; the current Apify listing is the reference for availability and pricing.
Questions about this actor
What data does ZipRecruiter Scraper return?
The documented output for ZipRecruiter Scraper includes id, url, title, company, logo, city, state and setting. Availability of each field depends on the source page and the selected mode.
How much does ZipRecruiter Scraper cost?
It costs $1.70 per 1,000 results on the Apify Free plan and from $1.00 on paid plans, with smaller per-run or optional feature charges listed on Apify. The Apify listing shows the current rate for every plan.
Which countries are covered?
United States only (ziprecruiter.com). The Canadian, UK and Irish ZipRecruiter sites are a deliberate gap: they use different page layouts and URL shapes that this actor has not been built or tested against.
Why can a filtered run return fewer jobs than Max listings?
workplace, maxSalary, externalApplyOnly, skipSponsored, remoteOnly, minSalary and the employment filter are screens over the loaded results, not site search parameters. Jobs they remove are not returned and not billed, and the search is then not treated as a complete read, so emitExpired will not mark jobs as gone after such a run. The state key (incremental mode) includes workplace, maxSalary and externalApplyOnly only when you set them; maxItemsPerSearch, descriptionMaxLength and omitEmptyFields only shape the 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.
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.
