ZipRecruiter Scraper API - US Jobs, Salary & Apply URL avatar

ZipRecruiter Scraper API - US Jobs, Salary & Apply URL

Pricing

from $0.77 / 1,000 jobs

Go to Apify Store
ZipRecruiter Scraper API - US Jobs, Salary & Apply URL

ZipRecruiter Scraper API - US Jobs, Salary & Apply URL

Scrape ZipRecruiter jobs in the US by title and place. Each row has the title, company, location, employment type, remote flag, posted date and the employer's own apply link, with pay split into the employer's figure and ZipRecruiter's estimate. $0.80 per 1,000 jobs.

Pricing

from $0.77 / 1,000 jobs

Rating

0.0

(0)

Developer

Dami's Studio

Dami's Studio

Maintained by Community

Actor stats

0

Bookmarked

5

Total users

3

Monthly active users

2 days ago

Last modified

Share

Scrape ZipRecruiter jobs with the employer's apply link and the pay marked published or estimated: search by title and place, or paste a search URL, and the jobs come back as rows with the 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 or Canadian location, or ZipRecruiter URLs
OutputOne row per job: title, company, full location, employment type, remote flags, benefits, posted and reposted dates, employer apply link, pay with its source
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 on the Free plan, a little less on paid plans. The free plan's $5 a month covers about 6,200

🔍 What ZipRecruiter Scraper does

Give it keywords and a location, or paste search URLs and job pages from the site. Leave the keywords empty and set a location and you get the jobs in that place.

Filter values are checked before anything runs. ZipRecruiter ignores a value outside its own vocabulary and returns the unfiltered board, 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 data you get from each ZipRecruiter job

What you getField
The job and its stable IDsid, openSeatId, title, url
The companycompanyName, companyId, companyUrl, companyLogo
Where the job islocationText, city, state, stateCode, postalCode, county, countryCode
On-site, remote or hybridlocationTypes, locationTypeText, isRemote, isHybrid, isInPerson
Contract typeemploymentTypes, employmentTypeText
Pay the employer publishedsalaryMin, salaryMax, salaryMinAnnual, salaryMaxAnnual, salaryInterval, salaryText, salaryCurrency
ZipRecruiter's own pay estimateestimatedSalaryMin, estimatedSalaryMax, estimatedSalaryMinAnnual, estimatedSalaryMaxAnnual, estimatedSalaryInterval
Where the pay figure came fromsalarySource, salaryIsPublishedByEmployer, salaryIsEstimate, salaryShownOnSiteAsEstimate
Benefitsbenefits, benefitsText
Posted, reposted and still openpostedAt, repostedAt, postedAtRelative, isReposted, isActive, isNew, updatedAt
How to applyapplyUrl, applyRedirectUrl, applyType, hasZipApply
The textshortDescription, and with includeDescription on: description, companyRating, companyReviewCount, companyWebsite, companyIndustry, companyHq
The search that found itsearchQuery, searchLocation, searchUrl, page, position, scrapedAt

▶️ How to scrape ZipRecruiter jobs

  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.

Start it with no keywords, location or URL and you get one sample row, which is not billed.

💰 How much does it cost to scrape ZipRecruiter jobs?

$0.80 per 1,000 jobs on the Free plan, a little less on paid plans. On the free plan, the $5 Apify gives you each month covers about 6,200 jobs.

One billed row per job delivered. The sample row is not billed, diagnostic rows are not billed, and a posting dropped by the employer-published-pay filter never reaches the dataset and is not billed.

📥 What you give it

{
"searchQueries": ["registered nurse"],
"location": "Austin, TX",
"days": "5",
"locationType": "only_remote",
"employmentType": "full_time",
"maxItems": 200
}
FieldDefaultWhat it is
searchQueriesnone, the form opens with registered nurseOne search per entry. Leave empty and set a location for the jobs there.
locationnone, the form opens with Austin, TXA city and state, a state, or United States. For Canada, a city with its province, like Toronto, ON. Left empty, ZipRecruiter picks one area itself, so set it.
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, estimates included.
onlyEmployerPublishedSalaryoffKeep only employer-published pay. Dropped rows are not billed.
includeDescriptionoffFull description and the company's review score.
maxItemsnone, the form opens with 50Total jobs for the run, up to 20,000.
egressModeautoLeave it on auto.
proxyConfigurationnoneOptional. Only if you want the run to go out through servers 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"
}
FieldHow to read it
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. 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, as above.
isRemote, isHybridOften false on jobs ZipRecruiter files as remote or hybrid, because the record carries no location type. Read the limits below.

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 only marks the sample and diagnostic rows 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. It is left out with this note, and the search runs without it.
SEARCH_PAGE_UNAVAILABLETwo pages of results in a row did not come back, so that search stopped there.
TIME_LIMITThe run got close to its time limit and stopped on its own. The jobs delivered before that are complete and charged. Give the run more time, or ask for fewer jobs, to get the rest.

Notes never fail the run, except a TIME_LIMIT stop before any job came back.

💡 What people use it for

  • Pay benchmarking that holds up, 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 1 day and diffing on id.

Employer pay for one role across a state, then who else those employers want:

  1. Run this for registered nurse with location set to Texas and onlyEmployerPublishedSalary on.
  2. Compare salaryMinAnnual and salaryMaxAnnual by city. Every figure is the employer's own.
  3. Paste the busiest companyName values into Career Site Jobs Scraper to see the other roles they have open on their own careers page.

🚧 What it does not do

  • The US and Canada only. For Canada, write the city with its province, like Toronto, ON; pay comes back in Canadian dollars. ZipRecruiter's UK, Australian and other country sites are separate and are not read.
  • 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.
  • An empty location is not the whole country. ZipRecruiter picks one area. Type United States for a nationwide search.
  • The remote and hybrid flags miss a lot. In a test, 6 of 15 remote-only results and 1 of 10 hybrid ones carried the flag. Filter with On-site / remote instead of on isRemote.
  • Full descriptions and company ratings need the extra fetch, and even then not every posting carries a description. Around four in five do.
  • 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.
  • A pasted URL keeps only the filters this actor lists. Any other filter on it is dropped without a note.
  • postedAt can be years old on a reposted job. Read repostedAt alongside it.
  • It is not an official ZipRecruiter tool. Dami's Studio is independent and is not affiliated with or endorsed by ZipRecruiter, or by any other company named on this page.

🧭 Which jobs scraper do you need?

If you wantUse
US jobs with pay marked published or estimatedThis one
LinkedIn job postings by keyword and locationLinkedIn Jobs Scraper
Every open role on one company's careers page, with the apply linkCareer Site Jobs Scraper

❓ Questions people ask

Do I need a ZipRecruiter account?

No. These are public job pages, and there is nothing to sign in to.

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.

Yes. applyUrl is the employer's page. 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 call it from code or connect it to an AI assistant?

Yes. The API tab has ready-made code for Python, JavaScript and the command line. For Claude, ChatGPT or another MCP client, connect https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/ziprecruiter-scraper. Either way the run happens on your Apify account at the same price.

These are public job postings. Apify's write-up on the legality of web scraping 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.