How it will work: 3 steps
- Follow us on ApifyThe tool is built and waits in the queue for the Apify Store. Apify is the cloud platform where our tools run.
- Paste your input and press StartNo code needed: you fill in a form (the input). It already has a working example. For example:
nursein Job title or keyword. Each start is one run. - Download the resultsWhen the run ends, the results are in a table (the dataset). Open Output, press Export and pick Excel or CSV. JSON and the API are there too.
This tool is an Apify Actor: a small program that runs on Apify. You can also run it on a schedule, for example every Monday. New to it? Read how it works, step by step and the 8 words you need first.
What it does
This Actor searches ZipRecruiter by job title and US location and saves each job as a row with pay, full job text and employer details.
Good for
- You recruit in the US and want open jobs by title and city in a spreadsheet.
- You compare pay for one role across cities.
- You look for employers that hire now, with company website and size.
- You need remote, hybrid or on-site jobs from one source, updated on a schedule.
Who uses it
Recruiters
Get open jobs by title and city in a spreadsheet.
Pay researchers
Compare pay for one role across cities.
Hiring trackers
Find employers that hire now, with company website and size.
Price
Prices will be shown after release.
Questions
Do I need a ZipRecruiter account or a login?
No. The Actor reads public job pages. You need only an Apify account.
Why is salary sometimes null?
ZipRecruiter does not show that value for this job. The Actor does not guess it.
Does it return all jobs on ZipRecruiter?
No. It returns what the site shows for your searches. Results change between runs.
How can I get more than 60 jobs from one search?
Keep deepSearch on. The Actor repeats the search with narrower filters and removes duplicates. In our tests one search returned 633 jobs. For more, add values in additionalQueries or additionalLocations. Our largest test run saved 1400 jobs with 4 titles.
How fresh is the data?
Each row has fetchedAt: the time the Actor read the job. postedAt is the first posting date and refreshedAt is the last update of the listing. A job can close soon after the run.
Details
Step by step on Apify
- Open the Input tab. Keep
nurseinquery(box 1 in the picture). - Keep
Chicago, ILinlocation(box 2). - Keep
20inmaxItems(box 3). This value is the form prefill. If you leave the field out in an API call, the default is 100. - Click Start.
- Open the Output tab and check pay in the
salarycolumn (box 5). - Read the full job text in the
descriptioncolumn (box 6).
Use cases
| Task | Input | You get | Key fields | Next step |
|---|---|---|---|---|
| Find open roles for a client | query, location, postedWithinDays | Job | title, company, postedAt, url | CSV or Excel export |
| Compare pay across cities | query, additionalLocations, minSalary | Job | salaryMin, salaryMax, salaryInterval, state | API or Dataset export |
| Find employers that hire now | query, location, includeCompanyDetails | Job with company data | company, companyDetails, companyUrl | CSV export to your own list |
| Watch remote jobs | query, remote, employmentTypes | Job | title, remote, locationType, refreshedAt | Schedule, then Slack or Notion summary |
| Re-read jobs you saved earlier | startUrls | Job | jobId, isActive, salary, description | API |
Tips for better results
- ZipRecruiter shows at most 60 jobs for one search. Keep deepSearch on to get more.
- Add values in additionalQueries or additionalLocations to reach your maxItems.
- Allow about 1 second per job above 200 when you set the run timeout.
Limits and good to know
- United States only
maxItemsis 1 to 1400 per run. Our runs of 1000 to 1400 jobs with job text took 556 to 1046 seconds. The longest one ran while the source was blocking job pages. Our latest large run saved 921 jobs in 426 secondsqueryand form filters work on ZipRecruiter search pages. The source decides which jobs a filter returns- One search does not always reach your
maxItems. In our tests one search stopped at 633 jobs when new jobs ran out, and runs of 1400 jobs with 5 and 8 broad titles ended at 1221 and 1350 jobs. Add titles or locations to get more - With
deepSearchoff, one search returns at most 60 jobs - One run can have up to 500 searches.
additionalQueriesandadditionalLocationsaccept up to 50 values each.startUrlsaccepts up to 500 links startUrlsaccepts onlyhttps://www.ziprecruiter.comlinks of three kinds:/jobs-search,/Jobs/and/c/.../Job/...?jid=...- The Run timeout must be at least 60 seconds. Above 200 jobs, allow about 1 second per job. The Actor's own time limit is 240 seconds plus 1 second per job above 200. At that limit, or at the Run timeout, the run stops and keeps saved rows. It also stops with
DEADLINEafter 240 seconds with no usable page from the source, at anymaxItems. With no saved rows, that run ends asFAILED
For developers
Sample result
One result from a real test run, in JSON. Real values change from run to run. In Excel or CSV each field is a column.
{
"jobId": "bd4991f117d2c90d",
"title": "Hospice Registered Nurse, RN",
"company": "Residential Home Health and Hospice",
"location": "Chicago, IL",
"salary": "$70K - $85K/yr",
"employmentType": "FULL_TIME",
"remote": null,
"postedAt": "2026-10-20T09:28:00.000Z",
"description": "**Job Title **\n\nHospice Registered Nurse, RN\n\n**Location**...",
"url": "https://www.ziprecruiter.com/c/Residential-Home-Health-and-Hospice/Job/Hospice-Registered-Nurse,-RN/-in-Chicago,IL?jid=bd4991f117d2c90d",
"source": "ziprecruiter",
"fetchedAt": "2026-11-05T02:58:37.837Z",
"city": "Chicago",
"state": "IL",
"postalCode": "60695",
"country": "US",
"salaryMin": 70000,
"salaryMax": 85000,
"salaryInterval": "YEAR",
"salaryCurrency": "USD",
"salaryIsEstimated": false,
"employmentTypes": ["FULL_TIME"],
"benefits": ["Medical", "Dental", "Vision", "Life", "Retirement", "PTO"],
"seniority": "junior",
"experienceMonths": 24,
"directApply": false,
"isActive": true,
"searchQuery": "nurse",
"searchLocation": "Chicago, IL",
"companyDetails": null,
"skills": null,
"category": null
}Data fields (40)
| Field | Type | Meaning |
|---|---|---|
jobId | string | ZipRecruiter job ID (jid), stable between runs. Use for dedupe. |
title | string | Job title. |
company | string | Hiring company name. |
location | string | Location as shown on the listing. |
salary | string | Pay as shown on the listing. Null when not shown. |
employmentType | string | Primary employment type, for example FULL_TIME. |
remote | boolean | True for remote jobs, false for hybrid or on-site, null when the source does not say. |
postedAt | string | Posting date, ISO 8601. |
description | string | Full job description as text. Null when not requested or not available. |
url | string | Job page on ZipRecruiter. |
source | string | Always ziprecruiter. |
fetchedAt | string | When this row was read, ISO 8601. |
listingKey | string | Source listing key, present on rows from search pages. |
city | string | City. |
state | string | State code. |
postalCode | string | Postal code. |
country | string | Country code. |
companyUrl | string | Company page on ZipRecruiter. |
companyLogo | string | Company logo URL. |
salaryMin | number | Minimum pay in salaryInterval units. |
salaryMax | number | Maximum pay in salaryInterval units. |
salaryMinAnnual | number | Minimum pay converted to a year by the source. |
salaryMaxAnnual | number | Maximum pay converted to a year by the source. |
salaryInterval | string | HOUR, DAY, WEEK, MONTH or YEAR. |
salaryCurrency | string | Pay currency, for example USD. |
salaryIsEstimated | boolean | True when the source estimated the pay instead of the employer stating it. |
employmentTypes | array | All employment types. |
benefits | array | Benefits listed by the source. |
locationType | string | IN_PERSON, REMOTE, HYBRID or REMOTE_OPTIONAL. |
refreshedAt | string | When the source last refreshed the listing, in ISO 8601. The source's date filter and age follow this date. |
postedRelative | string | Age as shown, for example 3 days ago. |
validThrough | string | Listing end date. Needs company details. |
seniority | string | no_experience, junior, mid or senior. |
experienceMonths | number | Months of experience asked for. |
education | string | Education asked for. Needs company details. |
applyUrl | string | External apply link through ZipRecruiter. Null for direct apply. |
directApply | boolean | True when applying happens on ZipRecruiter. |
isActive | boolean | Whether the listing is active. |
searchQuery | string | Search that found this job. Null for direct job links. |
searchLocation | string | Location of that search. |
Input settings (19)
The main fields of the input form. With the API you send them as JSON.
| Setting | Name in the API | Type | Example value |
|---|---|---|---|
| Job title or keyword | query | string | "nurse" |
| Location | location | string | "Chicago, IL" |
| Maximum jobs | maxItems | integer | 20 |
| Search radius | radiusMiles | integer | 25 |
| Posted within (days) | postedWithinDays | integer | |
| Workplace | remote | string | "any" |
| Employment types | employmentTypes | array | |
| Experience levels | experienceLevels | array | |
| Minimum annual salary (USD) | minSalary | integer | |
| Maximum annual salary (USD) | maxSalary | integer | |
| Company name contains | companyName | string | |
| Include job descriptions | includeDescription | boolean | true |
| Include company details | includeCompanyDetails | boolean | false |
| Go past the 60-job limit | deepSearch | boolean | true |
| Additional job titles | additionalQueries | array | |
| Additional locations | additionalLocations | array | |
| ZipRecruiter URLs | startUrls | array | |
| Send results to (optional) | deliveryConnector | string | |
| Notion page or channel (optional) | deliveryTarget | string |



