# ZipRecruiter Scraper - Jobs, Salaries & Employer Leads (`scrapesage/ziprecruiter-scraper`) Actor

Scrape ZipRecruiter jobs by keyword and location: title, company, logo, city/state, on-site or remote, and pay as listed plus an annualised salary range. Optional full description, employment type, posted date and employer firmographics, plus deduplicated employer leads. No start fee.

- **URL**: https://apify.com/scrapesage/ziprecruiter-scraper.md
- **Developed by:** [Scrape Sage](https://apify.com/scrapesage) (community)
- **Categories:** Jobs, Lead generation, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 job scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## ZipRecruiter Scraper - Jobs, Salaries & Employer Leads

> **Disclaimer:** This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by ZipRecruiter, Inc. or any of its subsidiaries. All trademarks mentioned are the property of their respective owners. "ZipRecruiter" is referenced only to describe the publicly available website this Actor collects data from.

Scrape **ZipRecruiter job listings** by keyword and location and get back a genuinely complete record: **job title, company, company page, logo, city/state, on-site / remote / hybrid, and pay** — with every wage **normalised to an annual figure** so an hourly rate and a yearly band are finally comparable.

Turn on the detail pass and each job also carries the **full job description, employment type, posted date** and the hiring company's **firmographics — company size, year founded, HQ location and website**. That is what turns a job feed into a **qualified B2B lead list**: a company that is hiring is a company that is buying.

**No start fee.** You pay per job delivered, nothing else.

### Why this ZipRecruiter scraper

| | Standard mode | With **Fetch full job details** |
|---|---|---|
| Fields per job | **28** | **39** |
| Job title, company, company URL, logo | ✅ | ✅ |
| City, state, on-site / remote / hybrid | ✅ | ✅ |
| Pay as listed (`$28 - $35/hr`) | ✅ | ✅ |
| **Annualised salary min/max** | ✅ | ✅ |
| New / Quick-apply / Promoted badges | ✅ | ✅ |
| Stable `jobId` + canonical job URL | ✅ | ✅ |
| Full job description | — | ✅ |
| Employment type, posted date, valid-through | — | ✅ |
| ZIP code, country | — | ✅ |
| **Company size, year founded, HQ, website** | — | ✅ |
| Deduplicated **employer lead records** + `leadScore` | ✅ | ✅ (enriched) |
| Monitor mode — only jobs new since last run | ✅ | ✅ |

Standard mode reads everything off the search results, so it is fast and cheap. The detail pass opens each job page for the description and firmographics — richer, one extra render per job. You choose per run.

#### Salary you can actually sort on

ZipRecruiter prints pay as free text, in whatever unit the employer chose. This actor keeps the raw string **and** normalises it:

| `salaryText` | `salaryPeriod` | `salaryMinAnnual` | `salaryMaxAnnual` |
|---|---|---|---|
| `$28 - $35/hr` | HOUR | 58,240 | 72,800 |
| `$1.8K - $2.5K/wk` | WEEK | 93,600 | 130,000 |
| `$5K/mo` | MONTH | 60,000 | 60,000 |
| `$130K - $165K/yr` | YEAR | 130,000 | 165,000 |

The **Minimum annual salary** filter compares against the annualised figure, so a `$53.50/hr` role is correctly kept by a `$100,000` floor instead of being silently dropped.

### Example output

A real, unedited record from a detail-pass run:

```json
{
    "type": "job",
    "jobId": "72295d203bf506cc",
    "title": "Software Engineer",
    "company": "Eden Technologies Inc",
    "companyUrl": "https://www.ziprecruiter.com/co/Eden-Technologies-Inc/Jobs/-in-Lockhart,TX",
    "companySlug": "Eden-Technologies-Inc",
    "companyLogo": "https://www.ziprecruiter.com/svc/fotomat/.../2f1a8774.jpeg",
    "location": "Lockhart, TX",
    "city": "Lockhart",
    "state": "TX",
    "postalCode": "78644",
    "country": "US",
    "workArrangement": "On-site",
    "isRemote": false,
    "salaryText": "$130K - $165K/yr",
    "salaryMin": 130000,
    "salaryMax": 165000,
    "salaryPeriod": "YEAR",
    "salaryCurrency": "USD",
    "salaryMinAnnual": 130000,
    "salaryMaxAnnual": 165000,
    "employmentType": "Full-time",
    "postedDate": "2026-06-26",
    "validThrough": "2026-09-26",
    "isNew": false,
    "isQuickApply": true,
    "isPromoted": false,
    "isUrgentlyHiring": false,
    "description": "Eden Technologies is hiring a Software Engineer to …",
    "companySize": "11 - 50",
    "companyFoundedYear": 2016,
    "companyHqLocation": "Austin, TX, US",
    "companyWebsite": "https://edentech.example",
    "jobUrl": "https://www.ziprecruiter.com/c/Eden-Technologies-Inc/Job/Software-Engineer/-in-Lockhart,TX?jid=72295d203bf506cc",
    "searchQuery": "software engineer",
    "searchLocation": "Austin, TX",
    "scrapedAt": "2026-08-28T01:43:52.000Z"
}
```

And an `employer` lead record (turn on **Emit employer leads**):

```json
{
    "type": "employer",
    "company": "Methodist Health System",
    "companyUrl": "https://www.ziprecruiter.com/co/Methodist-Health-System/Jobs",
    "companySize": "5,001 - 10,000",
    "companyFoundedYear": 1927,
    "companyHqLocation": "Dallas, TX, US",
    "companyWebsite": "https://methodisthealthsystem.example",
    "jobCount": 7,
    "locations": ["Alvarado, TX", "Dallas, TX"],
    "sampleTitles": ["Registered Nurse - Emergency Department - Nights", "RN Homecare"],
    "remoteJobs": 0,
    "minAdvertisedSalaryAnnual": 58240,
    "medianAdvertisedSalaryAnnual": 76960,
    "maxAdvertisedSalaryAnnual": 111280,
    "leadScore": 82
}
```

### Input

```json
{
    "searchQueries": ["registered nurse", "nurse practitioner"],
    "locations": ["Dallas, TX", "Austin, TX"],
    "maxJobs": 200,
    "includeJobDetails": true,
    "deduplicateEmployers": true,
    "salaryMin": 90000
}
```

| Field | Description |
|---|---|
| **Search queries** | Job titles or keywords. Each query runs against every location. |
| **Locations** | `City, ST`, a state, a ZIP code, or `Remote`. |
| **Start URLs** | Paste ZipRecruiter search-result or job URLs directly — supports **Link remote text file** and file upload. |
| **Max jobs** | Cap across all searches. `0` = no limit (bounded by the run timeout). |
| **Fetch full job details** | Adds description, employment type, posted date and company firmographics. One extra render per job. |
| **Emit employer leads** | Also output one deduplicated `employer` record per hiring company, with `leadScore`. |
| **Remote jobs only** | Keep only roles flagged remote. |
| **Employment type** | Full-time, part-time, contract, temporary, internship. |
| **Minimum annual salary** | Annualised comparison — see the salary table above. |
| **Monitor mode** | Only output jobs that are new since the previous run. Pairs with [Schedules](https://docs.apify.com/platform/schedules). |
| **Proxy** | **Residential required** (default). ZipRecruiter blocks datacenter IPs. |

### Three ready-made dataset views

- **Jobs** — title, company, location, arrangement, pay, annualised min/max, new flag, URL.
- **Salaries** — pay-focused: raw pay, period, annualised band, currency.
- **Employer leads** — company, open-job count, size, founded, HQ, website, median pay, lead score.

### Use cases

- **Recruiting & sourcing** — see who is hiring for a role in a market right now, with real pay bands.
- **B2B lead generation** — hiring companies, deduplicated, scored, with firmographics and a website to enrich against.
- **Compensation benchmarking** — annualised pay across hundreds of postings, comparable across hourly and salaried roles.
- **Labour-market research** — track hiring volume, remote share and pay by city, role and employer over time.
- **Job boards & alerts** — schedule with Monitor mode and publish only genuinely new postings.

### Automate & schedule

- **[Schedules](https://docs.apify.com/platform/schedules)** — run daily with Monitor mode for a rolling feed of new postings.
- **[Webhooks](https://docs.apify.com/platform/integrations/webhooks)** — push new employer leads into your CRM the moment a run finishes.
- **[apify-client for JavaScript](https://docs.apify.com/api/client/js/)** / **[Python](https://docs.apify.com/api/client/python/)**.

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'MY_APIFY_TOKEN' });

const run = await client.actor('scrapesage/ziprecruiter-scraper').call({
    searchQueries: ['registered nurse'],
    locations: ['Dallas, TX'],
    maxJobs: 200,
    includeJobDetails: true,
    deduplicateEmployers: true,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`${items.filter((i) => i.type === 'job').length} jobs, ${items.filter((i) => i.type === 'employer').length} employer leads`);
```

### Integrate with any app

- **[Make](https://docs.apify.com/platform/integrations/make)** · **[Zapier](https://docs.apify.com/platform/integrations/zapier)** — push leads into your CRM.
- **[Slack](https://docs.apify.com/platform/integrations/slack)** — alert on new postings for a watched role.
- **[Google Drive / Sheets](https://docs.apify.com/platform/integrations/drive)** — auto-export every run.
- **[Airbyte](https://docs.apify.com/platform/integrations/airbyte)** — pipe into your warehouse.

### Use with AI assistants (MCP)

Clean, LLM-ready JSON. Call it from Claude, ChatGPT or any agent framework through the **[Apify MCP server](https://docs.apify.com/platform/integrations/mcp)** — *"which companies in Dallas are hiring nurses above $100k, and how big are they?"* is a single tool call.

### Agent-ready: autonomous payments (x402 & Skyfire)

This actor is **agent-ready** — AI agents can discover it, run it, and **pay for it autonomously**, with no Apify account and no human in the loop. It uses [pay-per-event](https://docs.apify.com/platform/actors/publishing/monetize/pay-per-event) pricing and [limited permissions](https://docs.apify.com/platform/actors/development/permissions), so it qualifies for Apify's agentic-payment standards:

- **[x402](https://docs.apify.com/platform/integrations/x402)** — an open, HTTP-native payment protocol. Agents pay per run in USDC on the Base network directly through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp) — no account, no API key.
- **[Skyfire](https://docs.apify.com/platform/integrations/skyfire)** — agent-to-service payments for fully autonomous AI-agent workflows.

Building an AI agent, MCP tool, or autonomous data pipeline? This scraper is ready to plug in and pay as it goes.

### Pricing

Pay-per-event, **no start fee** — you are charged only for what is delivered.

| Event | Price |
|---|---|
| `job` — one job record | $0.004 |
| `employer` — one deduplicated employer lead | $0.008 |

Employer leads are opt-in, so a plain job run is billed on `job` alone.

### More scrapers from scrapesage

- **[Naukri Scraper](https://apify.com/scrapesage/naukri-scraper)** — India jobs, salaries & recruiter leads.
- **[Foundit Scraper](https://apify.com/scrapesage/foundit-scraper)** — India, Gulf & SE Asia jobs with recruiter phones.
- **[LinkedIn Jobs Scraper](https://apify.com/scrapesage/linkedin-jobs-scraper)** — filter-based postings, no login.
- **[LinkedIn Company Scraper](https://apify.com/scrapesage/linkedin-company-scraper)** — firmographics & B2B leads.
- **[Multi-ATS Job Scraper](https://apify.com/scrapesage/multi-ats-job-scraper)** — Greenhouse, Lever, Ashby & Workday.
- **[Glassdoor Scraper](https://apify.com/scrapesage/glassdoor-scraper)** — company reviews, ratings & interviews.
- **[Levels.fyi Scraper](https://apify.com/scrapesage/levels-fyi-scraper)** — tech salaries & leveling.
- **[Talent.com Jobs Scraper](https://apify.com/scrapesage/talent-com-jobs-scraper)** — listings, salaries & employer leads.
- **[Remote Jobs Scraper](https://apify.com/scrapesage/remote-jobs-scraper)** — 7 remote boards in one run.
- **[Website Contact Scraper](https://apify.com/scrapesage/website-contact-scraper)** — emails & phones from any company site.

### Tips

- **Start in standard mode** to size a market cheaply, then re-run the shortlist with **Fetch full job details** for descriptions and firmographics.
- **Split wide markets by city.** ZipRecruiter caps how deep a single search paginates, so `Dallas, TX` + `Austin, TX` + `Houston, TX` returns far more than one statewide search.
- **Dedupe on `jobId`** across scheduled runs; dedupe on `company` for a clean employer list.
- **Employer leads get much richer** when the detail pass is on — that is where size, founded year, HQ and website come from.
- **Keep the residential proxy.** Datacenter IPs do not clear ZipRecruiter's Cloudflare challenge.

### FAQ

**Do I need a ZipRecruiter login or API key?** No.

**Why is a residential proxy required?** ZipRecruiter sits behind a Cloudflare *managed* challenge. Datacenter IPs are refused; the actor runs a real headful browser on residential IPs, which clears it.

**How often is pay actually shown?** It depends heavily on the role and market — measured **50% to 92%** across four test markets (50% for warehouse roles in Atlanta, 92% for electricians in Tampa). ZipRecruiter only displays pay when the employer discloses it; where it is absent the salary fields are `null`, never estimated.

**Why do some company fields come back empty?** Firmographics come from the employer's own ZipRecruiter company profile. Measured across test runs, **two thirds to three quarters** of employers publish size, HQ and website; **year founded** is the least-completed at **33-58%**. Missing values are `null`, never invented.

**Is `postedDate` exact?** On the detail pass it comes from the posting's own structured data, normalised to `YYYY-MM-DD`. Every date in the column uses that one format.

**Can I get only new jobs?** Yes — turn on Monitor mode and schedule it. Only postings unseen in previous runs are emitted (and billed).

**What does a run cost?** 200 jobs in standard mode is $0.80 in event fees plus a few cents of compute. There is no start fee.

**Is scraping ZipRecruiter legal?** This actor collects publicly displayed job-listing data. You are responsible for using it in compliance with applicable law and ZipRecruiter's terms of use — please review those before running it at scale.

### Disclaimer

**This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by ZipRecruiter, Inc. or any of its subsidiaries. All trademarks mentioned are the property of their respective owners.**

"ZipRecruiter" and any related marks are the property of their respective owners and are used here only in a descriptive, nominative sense - to identify the publicly accessible website from which this Actor collects data. This Actor is not an official ZipRecruiter product, is not authorised or certified by ZipRecruiter, Inc., and does not distribute ZipRecruiter software. It collects only publicly available information; you are responsible for ensuring your use of that data complies with applicable laws, regulations and the terms of the source website.

### Need help?

Open an issue on the actor's **Issues** tab, or visit the [Apify help center](https://help.apify.com/). Feature requests are welcome.

***

*Independent scraper for publicly displayed data. Not affiliated with, endorsed by, or sponsored by ZipRecruiter. "ZipRecruiter" is a trademark of its respective owner, used here for descriptive purposes only.*

# Actor input Schema

## `searchQueries` (type: `array`):

Job titles or keywords to search, e.g. <code>registered nurse</code>, <code>software engineer</code>, <code>truck driver</code>. Each query is combined with every location below.

## `locations` (type: `array`):

Where to search — <code>City, ST</code> (<code>Dallas, TX</code>), a state, a ZIP code, or <code>Remote</code>. Each location is combined with every search query.

## `startUrls` (type: `array`):

Direct ZipRecruiter URLs — search result pages (<code>https://www.ziprecruiter.com/jobs-search?search=...\&location=...</code>) or individual job pages. Used in addition to the searches above.

## `maxJobs` (type: `integer`):

Maximum number of jobs to scrape across all searches. Set <code>0</code> for no limit (bounded by the run's time budget and ZipRecruiter's pagination).

## `includeJobDetails` (type: `boolean`):

Open each job page to also extract the <b>full job description</b>, <b>employment type</b>, <b>posted date</b>, benefits and the hiring company's <b>firmographics</b> (company size, year founded, HQ location, website). Costs one extra page render per job. When off (default) you still get everything the result cards carry: title, company + company URL, logo, location, on-site/remote/hybrid, pay (raw and annualised) and the job URL.

## `deduplicateEmployers` (type: `boolean`):

In addition to job records, output one deduplicated <code>employer</code> record per hiring company — open-job count, locations, sample titles, remote-role count, advertised salary range and a 0-100 <code>leadScore</code>. Turn on <b>Fetch full job details</b> as well to enrich each employer with company size, year founded, HQ and website. Active hiring is a strong B2B buying signal.

## `remoteOnly` (type: `boolean`):

Only keep jobs ZipRecruiter flags as remote (work arrangement "Remote", or a remote-titled role).

## `employmentType` (type: `string`):

Keep only jobs of this employment type.

## `salaryMin` (type: `integer`):

Keep only jobs paying at least this much per year. Hourly, weekly and monthly pay is <b>annualised before the comparison</b> (e.g. $53.50/hr counts as ~$111,280/yr), so you will not lose hourly roles that clear the bar. Jobs with no advertised pay are excluded when this is set. Leave empty for no filter.

## `monitorMode` (type: `boolean`):

Remember jobs seen in previous runs and only output listings that are <b>new</b> since last time. Ideal with a <a href='https://docs.apify.com/platform/schedules' target='_blank' rel='noopener'>Schedule</a> to track a role or market. State is kept in a named key-value store and does not interfere with the Apify scheduler.

## `proxyConfiguration` (type: `object`):

Proxies used for every request. <b>Residential proxies are required</b> — ZipRecruiter sits behind a Cloudflare managed challenge that datacenter IPs do not clear. The default (Apify residential, US) is the tested configuration.

## Actor input object example

```json
{
  "searchQueries": [
    "registered nurse"
  ],
  "locations": [
    "Dallas, TX"
  ],
  "maxJobs": 100,
  "includeJobDetails": false,
  "deduplicateEmployers": false,
  "remoteOnly": false,
  "employmentType": "any",
  "monitorMode": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (type: `string`):

All scraped job records and optional employer lead records as JSON items in the default dataset.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchQueries": [
        "registered nurse"
    ],
    "locations": [
        "Dallas, TX"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapesage/ziprecruiter-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchQueries": ["registered nurse"],
    "locations": ["Dallas, TX"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapesage/ziprecruiter-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchQueries": [
    "registered nurse"
  ],
  "locations": [
    "Dallas, TX"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call scrapesage/ziprecruiter-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapesage/ziprecruiter-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/7UX2m00giynlBmVxE/builds/WYbN3EnJaTRjs9kEV/openapi.json
