Request a tool
All toolsAutomationsGuidesMCP serverRequest a toolPlatformsCategories
ZipRecruiter Scraper icon

ZipRecruiter Scraper

Scrape ZipRecruiter jobs by keyword, city, remote or salary. Exact posted dates, apply URLs, pay marked published or estimated. $0.80 per 1,000.

122 runs on Apify $0.0008 per job ($0.8 / 1,000)
Run this in the cloudRun on Apify →

Job Market Scrapers

How it works

  1. 1
    Open it on Apify

    Hit Run on Apify — it opens the tool in the cloud, no install.

  2. 2
    Set the inputs

    Adjust searchQueries, location, startUrls (sensible defaults are pre-filled).

  3. 3
    Click Run

    The tool runs on Apify’s cloud and collects the data for you.

  4. 4
    Export the results

    Download as JSON, CSV or Excel, or pipe straight into your app, Google Sheets, or an AI agent.

Pricing

$0.0008 per job = $0.8 per 1,000

You are charged forWhenPrice
Job returnedCharged once per genuine ZipRecruiter posting: title, company, city and state, employment type, remote/hybrid flag, benefits, the exact ISO posted date, the employer apply URL, and pay with a source flag separating employer-published figures from ZipRecruiter estimates. Sample rows, diagnostics, duplicates, and rows dropped by the employer-published-pay filter are never charged.$0.0008

Pay-per-event pricing: you are billed per result, not per subscription. Billing is handled by Apify on your own account. These are the live Apify store prices, in effect since 2026-08-09, and they are what you are actually charged.

Inputs

FieldWhat it doesType
searchQueriesOne search per entry, for example "registered nurse" or "warehouse associate". Leave empty and set a location to get every job in that place.array
locationA city and state ("Austin, TX"), a state ("Texas") or "United States". ZipRecruiter is a US board; ziprecruiter.ca and .co.uk do not serve this data.string
startUrlsPaste ZipRecruiter search URLs (https://www.ziprecruiter.com/jobs-search?search=...&location=...) or individual job pages (https://www.ziprecruiter.com/c/{Company}/Job/{Title}/-in-{City},{ST}?jid=...). Search filters in the URL are read and re-used.array
maxItemsStop after this many jobs. You are charged only for jobs actually returned.integer
daysOnly jobs posted in the last N days. ZipRecruiter accepts exactly these values; anything else is ignored by the site and silently returns the unfiltered list, so it is rejected here instead.string
radiusDistance from the location. Ignored for state-wide and country-wide locations.string
locationTypeRestrict to on-site, remote or hybrid postings. Uses ZipRecruiter’s own location-type facet.string
employmentTypeRestrict to one employment type. "As needed / per diem" is ZipRecruiter’s PRN bucket.string
experienceLevelRestrict to one seniority band, as classified by ZipRecruiter.string
applyType"1-Click Apply" restricts the search to postings that accept an application on ZipRecruiter itself.string
salaryMinZipRecruiter's own salary filter. It uses the site's pay figure, which for some postings is an estimate - see "Only employer-published pay" below if you need certainty.integer
salaryMaxZipRecruiter’s salary ceiling filter, as a whole-dollar annual figure.integer
onlyEmployerPublishedSalaryKeep only postings whose pay came from the employer (a structured pay field, or pay written into the job description). Drops ZipRecruiter's own estimates. Dropped rows are NOT charged. About 76% of postings survive this filter.boolean
includeDescriptionAdds the complete job description plus the employer's ZipRecruiter review score and review count. Costs one extra request per job, so a run takes roughly three times longer. Without it you still get a ~200-character summary.boolean
egressModeLeave this on "auto" unless a run gets challenged repeatedly, then try another option.string

What you get

A structured dataset — each result includes fields like:

titlecompanyNamelocationTextemploymentTypeTextisRemotesalaryTextsalarySourcesalaryIsEstimateestimatedSalaryTextpostedAtpostedAtRelativebenefitsTextapplyUrlurlsalaryIsPublishedByEmployersalaryShownOnSiteAsEstimatesalaryMinsalaryMaxsalaryIntervalestimatedSalaryMinestimatedSalaryMax

Export every run as JSON, CSV or Excel, or send it to your app, a database, Google Sheets, or an AI agent.

Related tools in Job Market Scrapers

Other ready-to-run tools in the same category — all pay-per-use on the Apify cloud.

LinkedIn Company Employees Scraper iconJob Market Scrapers

LinkedIn Company Employees Scraper

Find a company's employees on LinkedIn, no login. Give a company URL or name. Get name, headline, job title, location and profile URL. $1.80 per 1,000.

1 use cases

Indeed Jobs Scraper iconJob Market Scrapers

Indeed Jobs Scraper

Scrape Indeed jobs by keyword and location in 11 countries. Get company, salary, benefits, remote flag, employer rating and apply URL. $4.00 per 1,000.

16 use cases

Glassdoor Company Reviews Scraper iconJob Market Scrapers

Glassdoor Company Reviews Scraper

Scrape Glassdoor reviews: pros, cons, six sub-ratings, recommend rate and CEO approval. First page per company without login. $2.50 per 1,000.

20 use cases

StepStone Jobs Scraper iconJob Market Scrapers

StepStone Jobs Scraper

Scrape StepStone jobs in DE, AT, NL and BE by keyword and location. Get company, salary, posted date, remote flag and links. $3.00 per 1,000 jobs.

4 use cases

Remotive Jobs Scraper iconJob Market Scrapers

Remotive Jobs Scraper

Scrape remote jobs from Remotive by keyword or category: company, region, salary, tags and plain-text descriptions. $2.00 per 1,000 jobs.

3 use cases

Multi-ATS Jobs Scraper (Greenhouse, Lever, Ashby) iconJob Market Scrapers

Multi-ATS Jobs Scraper (Greenhouse, Lever, Ashby)

Scrape open jobs from Greenhouse, Lever and Ashby boards. Get the title, location, department, posted date, description and apply link. $3.00 per 1,000.

3 use cases

See all Job Market Scrapers →

ZipRecruiter Scraper: US jobs with the apply URL and pay marked published or estimated

Search ZipRecruiter by title and place, or paste a search URL, and every job comes back as a row: title, company, city and state, employment type, remote or on-site, the exact posted date, and the employer's own apply link rather than a redirect.

The awkward part first, and it is the reason this exists. A lot of the pay on ZipRecruiter is ZipRecruiter's own estimate, not the employer's number. Rows keep the two apart: employer figures live in salaryMin and salaryMax, estimates live in estimatedSalaryMin and estimatedSalaryMax, and salarySource says exactly where the number came from. They are never mixed into one column.

InputJob titles or keywords with a US location, or ZipRecruiter URLs
OutputOne row per job
Ceiling20,000 jobs per run. About 750 per search is ZipRecruiter's own limit
Account neededNone, and nothing to install
Price$0.80 per 1,000 jobs, flat on every plan

🏷️ What ZipRecruiter Scraper does

Give it keywords and a location, or paste ZipRecruiter search URLs and job pages. A pasted search URL keeps the filters already on it. Leave the keywords empty and set a location and you get everything in that place.

Filter values are checked before anything runs. ZipRecruiter ignores a value outside its own vocabulary and returns the unfiltered board at HTTP 200, so a typo would quietly get you every job in the country and bill you for it. Only values the site actually honours are accepted here, which is why the filters are pick-lists rather than free text.

onlyEmployerPublishedSalary is the strict version of the pay promise: it keeps only postings whose figure came from the employer, either as a structured pay field or written into the description, and drops ZipRecruiter's estimates. About 76% of postings survive it. Dropped rows never reach the dataset and are not billed.

includeDescription adds the full description plus the employer's ZipRecruiter review score and review count. It costs one extra request per job, so the run takes roughly three times as long. It adds fields rather than rows, so the price does not move. Without it you still get a summary of around 200 characters.

📥 What you give it

{
  "searchQueries": ["registered nurse"],
  "location": "Austin, TX",
  "days": "5",
  "locationType": "only_remote",
  "employmentType": "full_time",
  "maxItems": 200
}
FieldDefaultWhat it is
searchQueriesbox starts at registered nurseOne search per entry. Leave empty and set a location for everything there.
locationbox starts at Austin, TXA city and state, a state, or United States. US board only.
startUrlsnoneZipRecruiter search URLs or individual job pages, pasted from the site.
daysany timePosted within the last 1, 5, 10 or 30 days.
radiusZipRecruiter's own 25 miles5, 10, 25, 50 or 5000 miles. Ignored for state-wide and country-wide searches.
locationTypeanyno_remote, only_remote or hybrid.
employmentTypeanyFull-time, part-time, contract, contract to hire, temporary, per diem or other.
experienceLevelanyno_experience, junior, mid or senior, as ZipRecruiter classifies them.
applyTypeanyhas_zipapply keeps only postings you can apply to on ZipRecruiter itself.
salaryMin, salaryMaxnoneZipRecruiter's own annual salary filter, which uses its own pay figure.
onlyEmployerPublishedSalaryoffKeep only employer-published pay. Dropped rows are not billed.
includeDescriptionoffFull description and the company's review score.
maxItemsbox starts at 50Total jobs for the run, up to 20,000.
egressModeautoLeave it alone. The other settings are there for debugging.
proxyConfigurationleave it aloneOptional. Only if you want the run to go out through a particular network of your own.

📤 What you get back

A real row from a run on 20 September 2026, with the long redirect token cut short:

{
  "id": "EazrVIHe3SD2W9b_kEu68w",
  "openSeatId": "e8a515fa6f1a5372",
  "title": "RN, Registered Nurse - IMC MedSurgical A",
  "url": "https://www.ziprecruiter.com/c/CHRISTUS-Health/Job/RN,-Registered-Nurse-IMC-MedSurgical-A/-in-San-Marcos,TX?jid=e8a515fa6f1a5372",
  "companyName": "CHRISTUS Health",
  "companyId": "christus health",
  "companyUrl": "https://www.ziprecruiter.com/co/CHRISTUS-Health/Jobs",
  "locationText": "San Marcos, TX",
  "city": "San Marcos",
  "state": "Texas",
  "stateCode": "TX",
  "postalCode": "78666",
  "county": "Hays",
  "countryCode": "US",
  "locationTypes": ["IN_PERSON"],
  "locationTypeText": "On-site",
  "isRemote": false,
  "isHybrid": false,
  "isInPerson": true,
  "employmentTypes": ["FULL_TIME"],
  "employmentTypeText": "Full-time",
  "salarySource": "ziprecruiter_internal_model",
  "salaryIsEstimate": true,
  "salaryIsPublishedByEmployer": false,
  "salaryMin": null,
  "salaryMax": null,
  "salaryMinAnnual": null,
  "salaryMaxAnnual": null,
  "salaryInterval": null,
  "salaryCurrency": "USD",
  "salaryText": null,
  "estimatedSalaryMin": 31.25,
  "estimatedSalaryMax": 49.75,
  "estimatedSalaryMinAnnual": 62500,
  "estimatedSalaryMaxAnnual": 99500,
  "estimatedSalaryInterval": "HOUR",
  "salaryShownOnSiteAsEstimate": false,
  "benefits": [],
  "benefitsText": null,
  "postedAt": "2024-02-27T20:43:20Z",
  "repostedAt": "2026-09-14T20:43:20Z",
  "postedAtRelative": "5 days ago",
  "isReposted": false,
  "isActive": true,
  "isNew": false,
  "updatedAt": "2026-09-19T22:49:08.815300215Z",
  "applyType": "OPEN_EXTERNAL",
  "hasZipApply": false,
  "applyUrl": "https://careers.christushealth.org/opportunity/rn-registered-nurse-imc-medsurgical-a-325738?utm_campaign=ZipRecruiterPPC-RN",
  "applyRedirectUrl": "https://www.ziprecruiter.com/job-redirect?match_token=Cp8BChZFYXpyVklIZTNTRDJXOWJfa0V1Njh3...",
  "shortDescription": "Description CHRISTUS Santa Rosa Hospital - San Marcos, which originated in 1923 as Hays County Soldiers, Sailors and Marines Memorial Hospital, opened at its current Wonder World Drive location in",
  "description": null,
  "companyRating": null,
  "companyReviewCount": null,
  "searchQuery": "registered nurse",
  "searchLocation": "Austin, TX",
  "searchUrl": "https://www.ziprecruiter.com/jobs-search?search=registered+nurse&location=Austin%2C+TX",
  "page": 1,
  "position": 1,
  "scrapedAt": "2026-09-20T07:08:28.109Z"
}
FieldWhat it is
salarySourceemployer_provided, employer_description_parsed, ziprecruiter_estimate, ziprecruiter_internal_model or none. The first two are the employer's number.
salaryIsPublishedByEmployer / salaryIsEstimateThe same split as two booleans, for filtering in a spreadsheet.
salaryShownOnSiteAsEstimateWhether ZipRecruiter labels it as an estimate on its own page, which is not always the same thing.
applyUrlThe employer's own application page, decoded out of ZipRecruiter's redirect. applyRedirectUrl keeps the redirect if you want it.
postedAt / repostedAt / postedAtRelativeThe original posting date, when it was put back up, and ZipRecruiter's own wording. A row can carry an old postedAt and a recent repostedAt.
description, companyRating, companyReviewCount, companyWebsite, companyIndustry, companyHqOnly with includeDescription on.
searchQuery, searchLocation, searchUrl, page, positionWhich search produced the row, and the exact URL used.

Two dataset views are set up in the Console: overview, and salaryHonesty, which puts the published and estimated pay columns side by side.

🧾 Reading the output

RowHow to spot itBilled
A jobIt has an id and no ok keyyes
The sample row_sample: true and charged: falseno
A diagnosticok: false, _diagnostic: true and an errorCodeno

Job rows carry no charged field. The flag is only on the sample and diagnostic rows, to mark them as not real results. The sample row looks like a realistic posting in the Console table, so filter on _sample rather than reading by eye.

CodeWhat it means
NO_RESULTSThat search matched nothing.
BAD_URLA link that is not a ZipRecruiter search or job page.
JOB_UNAVAILABLEA pasted job has expired or been taken down.
UNKNOWN_FILTER_VALUEA filter value ZipRecruiter does not honour, refused before the search ran.
SEARCH_PAGE_UNAVAILABLEA page of results did not come back.

▶️ How to run it

1. Open ZipRecruiter Scraper and click Try for free. 2. Type a role into Job titles or keywords and a place into Location. 3. Set Posted within, On-site / remote and the other filters if you want to narrow it. 4. Set Maximum jobs. Start around 25 to see what the rows look like. 5. Click Start, then download the dataset as JSON, CSV or Excel, or read it from the Apify API.

💰 How much does it cost?

$0.80 per 1,000 jobs. Flat on every Apify plan, with no volume tiers.

One billed row per job delivered. The sample row is not billed, diagnostic rows are not billed, a posting dropped by the employer-published-pay filter never reaches the dataset and is not billed, and includeDescription adds fields rather than rows so it does not change the price.

💡 What people use it for

  • Pay benchmarking that is actually defensible, because estimates and employer figures sit in

separate columns.

  • Recruiting-market research: who is hiring for a role in a metro, and how the postings are worded.
  • Feeding an applicant tool with applyUrl, which points at the employer rather than a redirect.
  • Watching a role daily with Posted within at 24 hours and diffing on id.
  • Remote-market tracking, using locationType and the isRemote and isHybrid flags.

🚧 What it does not do

  • United States only. The Canadian and UK ZipRecruiter sites do not serve this data.
  • About 750 jobs per search is ZipRecruiter's own depth. Split by city, role or date window to

go wider rather than raising the cap.

  • No estimate dressed up as a salary. If the employer published nothing, salaryMin and

salaryMax stay null and the estimate stays in its own fields.

  • Full descriptions need the extra fetch, and even then not every posting carries one. Around

four in five do.

  • Company ratings need that fetch too. Without it companyRating and companyReviewCount are

null.

  • A single failed page of results is skipped and the run carries on, without a row in the

dataset marking the gap. Compare the count you asked for against the count you got.

  • postedAt can be years old on a reposted job. Read repostedAt alongside it.

🧭 Which jobs scraper do you need?

If you wantUse
US jobs with pay marked published or estimatedThis one
Startup jobs from WellfoundWellfound Jobs Scraper
Jobs in Germany, Austria and SwitzerlandXING Jobs Scraper
Jobs in Germany, Austria, the Netherlands and BelgiumStepStone Jobs Scraper
Internships and fresher jobs in IndiaInternshala Scraper

❓ Questions people ask

How do I get only real employer salaries? Turn on Only employer-published pay. Roughly three in four postings survive it, and the ones dropped are not billed.

What is the difference between the salary fields? salaryMin and salaryMax are the employer's own figure. estimatedSalaryMin and estimatedSalaryMax are ZipRecruiter's model. A row never puts one in the other's place.

Does the apply link go to the employer? Yes. applyUrl is the employer's page, decoded out of ZipRecruiter's redirect. applyRedirectUrl keeps the original if you need it.

Why is description empty? Turn on Fetch full description and company rating. It triples the run time, which is why it is off by default.

Can I paste a search I set up on the site? Yes. The filters on the URL are read and reused.

Is this legal? These are public job postings. Apify's write-up on scraping and the law is a good starting point, and we are not lawyers.

🆘 If something breaks

Open the Issues tab on the actor page. Send the search or URL you used and the run ID. The errorCode on the diagnostic row usually names the problem on its own.