# ZipRecruiter Scraper — Jobs by Keyword or URL + Employer Emails (`memo23/ziprecruiter-scraper-ppe`) Actor

ZipRecruiter scraper — search jobs by keywords, location or any search URL. Full postings: salary, employment type, remote flag, company, direct apply links. Opt-in employer contact-email enrichment for recruiting lead-gen. Filters for date, radius, easy-apply. Pay per result, JSON or CSV out.

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

## Pricing

from $5.00 / 1,000 job results

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use 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 by Keyword or URL + Employer Emails

Scrape **ZipRecruiter job listings** at scale: search by keyword + location or paste any ZipRecruiter search URL, and get full postings — salary, employment type, remote flag, company details, precise coordinates and direct/external apply links. Flip one toggle and the scraper also finds a **verified employer contact email** for each job's company — turning job data into ready-to-use recruiting and lead-gen lists.

### Pricing (pay per event)

| Event | Price | When charged |
|---|---|---|
| Actor start | $0.005 | Once per run (per GB of run memory) |
| **Job result** | **$0.005** | Per job pushed to the dataset |
| Employer email found | $0.02 | Only when opt-in enrichment finds a verified contact email |

**Example:** 1,000 jobs ≈ **$5**. With email enrichment on and a ~30% hit rate: 1,000 jobs + 300 emails ≈ **$11**. Emails are billed only when found — misses are free.

### Why Scrape ZipRecruiter?

ZipRecruiter is one of the largest job posting platforms in the United States, aggregating millions of job listings from various sources. Scraping ZipRecruiter offers invaluable data for:

1. Labor Market Analysis: Track job trends, salary ranges, and in-demand skills across industries and locations.
2. Competitive Intelligence: Monitor hiring patterns of competitors and identify emerging industry trends.
3. Recruitment Strategies: Gain insights into job descriptions, required qualifications, and benefits to optimize your own job postings.
4. Career Research: Analyze job requirements and salaries for specific roles to guide career decisions or negotiations.
5. Economic Research: Use job posting data as a leading indicator of economic health and industry growth.
6. AI and Machine Learning: Build robust datasets for training job matching algorithms or predictive models for career progression.

### What Can You Scrape?

Our enhanced ZipRecruiter scraper allows you to extract comprehensive information, including:

#### **Basic Job Information**
- Job titles, descriptions, and requirements
- Salary information and benefits
- Company details and profiles
- Job locations with precise coordinates
- Posting dates and application deadlines
- Employment type (Full-time, Part-time, Contract, etc.)

#### **Enhanced Data Extraction**
- **Structured Data**: Rich JSON-LD schema information
- **Meta Information**: SEO tags, Open Graph, and Twitter Card data
- **Social Sharing**: Facebook, LinkedIn, Twitter, and RSS links
- **Apply Information**: External application URLs and tracking data
- **Geographic Data**: Precise latitude/longitude coordinates
- **Technical Metadata**: Job source, feed information, and tracking tokens

#### **Traditional Data Points**
- Salary information and benefits
- Industry classifications and job categories
- Application methods and links
- Company logos and job listing images
- Remote work opportunities

By leveraging this comprehensive data extraction, you can gain deeper insights into the job market, identify trends, and make data-driven decisions for your business, research, or personal career growth.

### How it works

This actor allows you to scrape job listings from both ZipRecruiter.com (US) and ZipRecruiter.ie (Ireland) platforms, extracting detailed job information using advanced Cheerio-based parsing techniques.

### Features

**Multi-Region Support**: Now supports scraping from multiple ZipRecruiter domains:

#### **United States (ZipRecruiter.com)**
- https://www.ziprecruiter.com/jobs-search?form=jobs-landing&search=fire+alarm+technician&location=New+York%2C+NY
- https://www.ziprecruiter.com/jobs-search?search=software+engineer&location=San+Francisco%2C+CA
- https://www.ziprecruiter.com/jobs-search?search=data+analyst&location=Chicago%2C+IL

#### **Ireland (ZipRecruiter.ie)**
- https://www.ziprecruiter.ie/jobs/search?q=backend&l=&lat=&long=
- https://www.ziprecruiter.ie/jobs/search?q=software+engineer&l=Dublin%2C+Ireland
- https://www.ziprecruiter.ie/jobs/search?q=data+analyst&l=Cork%2C+Ireland

#### **India (ZipRecruiter.in)**
- https://www.ziprecruiter.in/jobs/search?q=Front+End+Developer&l=New+Delhi%2C+India
- https://www.ziprecruiter.in/jobs/search?d=20&l=New+Delhi%2C+India&lat=28.63&long=77.22&q=%22Front+End+Developer%22&sort=published_at
- https://www.ziprecruiter.in/jobs/search?q=Software+Engineer&l=Bangalore%2C+India

**Enhanced Data Extraction**: Utilizes advanced Cheerio-based parsing to extract:
- Complete structured data (JSON-LD schema)
- Meta tags and social media information
- Precise geographic coordinates
- Rich job descriptions with HTML formatting
- External application tracking data

### How to Use
1. Set Up: Ensure you have an Apify account and access to the Apify platform.
2. Configure Input: Set the search URL(s) for the job listings you want to scrape.
3. Configure Proxy: You need to use proxy settings for enhanced reliability and to avoid potential IP blocks, please use residential proxies from USA or Ireland.
4. (Optional) Set Max Items (parameter: maxItems) to limit the number of job listings to scrape.
5. (Optional) Enable `externalApplyOnly` to keep only jobs that redirect candidates to an external apply flow.
6. Run the actor and obtain the extracted data in your preferred format.
7. Data Collection: The scraper will output data in your chosen format, which can include JSON, CSV, Excel, or others as supported by Apify.

### Input Configuration
Here's an example of how to set up the input for scraping fire alarm technician jobs in New York:

```json
{
    "startUrls": [
        {
            "url": "https://www.ziprecruiter.ie/jobs/search?q=backend&l=&lat=&long="
        },
        {
            "url": "https://www.ziprecruiter.com/jobs-search?form=jobs-landing&search=fire+alarm+technician&location=New+York%2C+NY"
        }
    ],
    "maxItems": 1000,
    "maxConcurrency": 10,
    "minConcurrency": 1,
    "maxRequestRetries": 10,
    "externalApplyOnly": false,
    "enrichEmails": false,
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
}
````

### Output Structure

Each dataset item now includes two normalized apply fields:

- `isExternalApply`: `true` when the job uses an external apply flow.
- `externalApplyUrl`: the normalized external apply redirect URL when available.

When `externalApplyOnly` is enabled, only items with `isExternalApply: true` are emitted.

The output data typically includes:

```json
{
    "Title": "Full-Time Alarm technicians",
    "isExternalApply": false,
    "externalApplyUrl": "",
    "IsExternal": false,
    "IsNewJob": false,
    "IsOrganic": false,
    "IsActiveEmployer": false,
    "OrgName": "Securetell Inc",
    "OrgURL": "/co/Securetell-Inc/Jobs",
    "LocationURL": "/jobs-search?search=Fire Alarm Technician&location=Westbury,NY",
    "City": "Westbury",
    "State": "NY",
    "Benefits": null,
    "SaveJobURL": "[URL for saving the job]",
    "CompanyLogoURL": "",
    "IsJobSaved": false,
    "HasZipApply": true,
    "QuickApplyHref": "[URL for quick apply]",
    "ShowSalary": true,
    "FormattedSalary": "$25 Hourly",
    "FormattedSalaryShort": "$25 / hr",
    "SalarySource": "provided",
    "EmploymentType": "Full-Time",
    "EmploymentTags": {},
    "WhyWorkHereBlurb": "",
    "EncryptedQuizID": "827e0df3",
    "JobURL": "https://www.ziprecruiter.com/c/Securetell-Inc/Job/Full-Time-Alarm-technicians/-in-Westbury,NY?jid=dff3b05032fd7e28",
    "Href": "[URL for job application]",
    "ApplyURL": "",
    "AppliedStatus": 2,
    "FirstSeenDaysAgo": 24,
    "TapURL": "",
    "OpenInTab": false,
    "QuizID": 226379264,
    "Snippet": "Growing <b>Alarm</b> Company based in Nassau County is looking for Full-Time <b>technicians</b> with good&nbsp;...&nbsp;We install and service <b>fire</b> <b>alarms</b>, burglar <b>alarms</b>, and other security related systems. Candidates&nbsp;...",
    "Source": "ZipRecruiter",
    "LVK": "VklYGmxpudK3jnCJl23TbA.--NWLhYBIPs",
    "Lat": 40.75566101074219,
    "Lng": -73.5876235961914,
    "BuyerType": "subs_fulfillment",
    "Company": {
        "uuid": "zr_missing_company_default"
    },
    "ImpressionID": "5Z6lVs8Bhgoo29-8",
    "jobDetails": {
        "ListingVersionKey": "VklYGmxpudK3jnCJl23TbA.--NUpNgqqxo",
        "EncryptedQuizID": "",
        "JobTitle": "Full-Time Alarm technicians",
        "JobLocation": "Westbury, NY",
        "Description": "<h3>Job Description</h3><div><div>Growing Alarm Company based in Nassau County is looking for Full-Time technicians with good communication skills, willing to learn to join our team. We install and service fire alarms, burglar alarms, and other security related systems.<br><br></div>...[Full description]</div>",
        "PostedTime": "24 days ago",
        "CompanyDetails": {
            "Name": "Securetell Inc",
            "WhyWorkHereBlurb": "",
            "Description": "",
            "LogoURL": "",
            "Address": "",
            "City": "Westbury",
            "State": "NY",
            "CountryCode": "USA",
            "Zipcode": "11590",
            "SearchURL": "/co/Securetell/Jobs",
            "IsCompanyPageIndexed": false,
            "Website": "",
            "JoinedYear": "2021",
            "Followers": 14
        },
        "CompanyLogo": {
            "URL": "",
            "Width": "",
            "Height": ""
        },
        "IsDisplaySalary": true,
        "Salary": "$25 Hourly",
        "EmploymentType": "Full-Time",
        "Benefits": null,
        "SaveJobURL": "[URL for saving the job]",
        "RelatedDirpURL": "/jobs-search?search=Summer-Fire-Alarm-Technician&location=Westbury,-NY",
        "ZipApplyPaidJobPageURL": "[URL for ZipApply paid job page]",
        "IsJobSaved": false,
        "BackToJobsURL": "/Jobs/Summer-Fire-Alarm-Technician",
        "CanInterceptOnZR": true,
        "DisableJobApply": false,
        "HasCompanyTab": false,
        "JobIsClosed": false,
        "IsEstimatedPay": false,
        "IsRemote": false,
        "Industry": "Real Estate",
        "ExtendedJobDetails": null,
        "JobCategoryTitle": "Full-Time Alarm technicians",
        "JobPageImageData": {
            "ImagePath": "[URL for job page image]",
            "ImageAlt": "Securetell Inc job posting for a Full-Time Alarm technicians in Westbury, NY with a salary of $25 Hourly with a map of Westbury location.",
            "ImageTitle": "Full-Time Alarm technicians Job Opening in Westbury, NY at Securetell Inc"
        }
    }
}
```

#### Property Descriptions

- `isExternalApply`: Normalized boolean flag indicating whether the job uses an external apply flow
- `externalApplyUrl`: Normalized external apply redirect URL when ZipRecruiter exposes one
- `Title`: The title of the job listing
- `IsExternal`: Boolean indicating if the job is from an external source
- `IsNewJob`: Boolean indicating if this is a newly posted job
- `IsOrganic`: Boolean indicating if this is an organic (non-sponsored) listing
- `IsActiveEmployer`: Boolean indicating if the employer is actively hiring
- `OrgName`: Name of the organization offering the job
- `OrgURL`: URL path to the organization's ZipRecruiter page
- `LocationURL`: URL path for searching similar jobs in this location
- `City`: City where the job is located
- `State`: State where the job is located
- `Benefits`: List of benefits offered (null if not specified)
- `SaveJobURL`: URL for saving the job to a user's account
- `CompanyLogoURL`: URL of the company's logo image
- `IsJobSaved`: Boolean indicating if the job has been saved by the user
- `HasZipApply`: Boolean indicating if the job can be applied to via ZipRecruiter
- `QuickApplyHref`: URL for quick application process
- `ShowSalary`: Boolean indicating if the salary is displayed
- `FormattedSalary`: Formatted string of the salary
- `FormattedSalaryShort`: Short formatted string of the salary
- `SalarySource`: Source of the salary information
- `EmploymentType`: Type of employment (e.g., Full-Time, Part-Time)
- `EmploymentTags`: Additional tags related to employment
- `WhyWorkHereBlurb`: Short description of why to work at this company
- `EncryptedQuizID`: Encrypted ID for any associated quiz
- `JobURL`: Full URL of the job listing on ZipRecruiter
- `Href`: URL for applying to the job
- `ApplyURL`: Alternate URL for applying (if different from Href)
- `AppliedStatus`: Numeric status indicating if/how the job has been applied to
- `FirstSeenDaysAgo`: Number of days since the job was first seen
- `TapURL`: URL for mobile tap actions
- `OpenInTab`: Boolean indicating if the job should open in a new tab
- `QuizID`: ID of any associated quiz
- `Snippet`: Short snippet or summary of the job description
- `Source`: Source of the job listing (e.g., ZipRecruiter)
- `LVK`: Listing Version Key (unique identifier for the listing version)
- `Lat`: Latitude of the job location
- `Lng`: Longitude of the job location
- `BuyerType`: Type of buyer for this job listing
- `Company`: Object containing company information
- `ImpressionID`: Unique ID for this impression of the job listing

#### jobDetails Property Descriptions

- `ListingVersionKey`: Unique key for this version of the listing
- `EncryptedQuizID`: Encrypted ID of any associated quiz
- `JobTitle`: Title of the job
- `JobLocation`: Location of the job
- `Description`: Full HTML description of the job
- `PostedTime`: When the job was posted
- `CompanyDetails`: Object containing detailed company information
- `CompanyLogo`: Object containing company logo information
- `IsDisplaySalary`: Boolean indicating if salary is displayed
- `Salary`: Salary information
- `EmploymentType`: Type of employment
- `Benefits`: List of benefits (if any)
- `SaveJobURL`: URL for saving the job
- `RelatedDirpURL`: URL for related job searches
- `ZipApplyPaidJobPageURL`: URL for ZipApply paid job page
- `IsJobSaved`: Boolean indicating if the job is saved
- `BackToJobsURL`: URL to return to job search results
- `CanInterceptOnZR`: Boolean indicating if ZipRecruiter can intercept the application
- `DisableJobApply`: Boolean indicating if job application is disabled
- `HasCompanyTab`: Boolean indicating if there's a company information tab
- `JobIsClosed`: Boolean indicating if the job listing is closed
- `IsEstimatedPay`: Boolean indicating if the pay is an estimate
- `IsRemote`: Boolean indicating if the job is remote
- `Industry`: Industry category of the job
- `ExtendedJobDetails`: Additional job details (if any)
- `JobCategoryTitle`: Category title for the job
- `JobPageImageData`: Object containing image data for the job page

Note: Some fields may be empty or null depending on the specific job listing.

### External Apply Notes

- `externalApplyOnly` works best on search result URLs because the SERP payload contains the strongest apply metadata.
- Some individual job pages still expose `directApply` in their structured data even when the originating SERP card was external. The actor preserves the stronger SERP signal so external jobs are not dropped.
- `externalApplyUrl` may still point to a ZipRecruiter redirect URL. The final third-party destination is usually embedded behind that redirect token.

### Employer Contact Emails (opt-in)

Set `"enrichEmails": true` and every job record gains three extra fields:

- `contactEmail` — best verified email for the hiring company
- `contactWebsite` — the company website the email was found on
- `emailEnrichment` — full enrichment detail (all emails found, source, confidence)

Discovery uses the company name + location with a business-domain guard (no residential or junk domains) and on-site contact-page scraping. Charged only on success — $0.02 per email actually found.

### FAQ

**How much does a run cost?** $0.005 per job + $0.005 actor start. 500 jobs ≈ $2.51. Email enrichment adds $0.02 per email found (only when found).

**Do I need proxies?** Yes — use residential proxies (US for ziprecruiter.com; IE/IN for the regional sites). Apify RESIDENTIAL works out of the box.

**Which domains are supported?** ziprecruiter.com (US), ziprecruiter.ie (Ireland), ziprecruiter.in (India).

**Can I keep only external-apply jobs?** Yes — set `externalApplyOnly: true` to keep only jobs that redirect to an external ATS (ideal for sourcing direct employer application links).

### Support

- For issues or feature requests, please use the [Issues](https://console.apify.com/actors/78akVhKqjDtMKtIfv/issues) section of this actor.
- If you need customization or have questions, feel free to contact the author:
  - Author's website: <https://muhamed-didovic.github.io/>
  - Email: <muhamed.didovic@gmail.com>
  - My Apify Actors/Scrapers: <https://apify.com/memo23>

### Additional Services

- Request customization or whole dataset: <muhamed.didovic@gmail.com>
- If you need anything else scraped, or this actor customized, email: <muhamed.didovic@gmail.com>
- For API services of this scraper (no Apify fee, just usage fee for the API), contact: <muhamed.didovic@gmail.com>

### Explore More Scrapers

Job-market data from the same author: [Indeed](https://apify.com/memo23/apify-indeed-cheerio-ppr), [Glassdoor](https://apify.com/memo23/glassdoor-scraper-ppr), [LinkedIn Jobs](https://apify.com/memo23/linkedin-jobs-scraper), [Wellfound](https://apify.com/memo23/wellfound-jobs-scraper), [Naukri](https://apify.com/memo23/naukri-scraper), [StepStone](https://apify.com/memo23/stepstone-search-cheerio-ppr), [Monster](https://apify.com/memo23/monster-scraper), [Seek](https://apify.com/memo23/seek-scraper), [Reed](https://apify.com/memo23/reed-jobs-scraper), [TotalJobs](https://apify.com/memo23/totaljobs-scraper) — full catalog at [apify.com/memo23](https://apify.com/memo23).

### ⚠️ Disclaimer

This actor extracts only publicly available data from ZipRecruiter job listings, for legitimate uses such as market research, recruiting and analytics. It is not affiliated with or endorsed by ZipRecruiter. You are responsible for using the extracted data in compliance with applicable laws and ZipRecruiter's terms of service.

# Actor input Schema

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

One URL per row. Example: a full `jobs-search` URL with your keyword and location in the query string.

## `searchJobKeyword` (type: `string`):

Job title or skill, e.g. `nurse`, `react developer`. Maps to ZipRecruiter `search`.

## `searchLocation` (type: `string`):

City, state, region, or country, e.g. `Austin, TX` or `United States`. Maps to `location`.

## `searchCompany` (type: `string`):

Narrow results to one employer. Maps to `company`. Example below is for the form only—clear it if you want all companies.

## `searchPostedWithinDays` (type: `integer`):

Only show jobs posted in the last N days. Maps to ZipRecruiter `days`.

## `searchRadiusMiles` (type: `integer`):

Search radius around the location. Maps to `radius`.

## `searchEmploymentType` (type: `string`):

Maps to `refine_by_employment` (employment\_type:…).

## `searchRemoteOnly` (type: `boolean`):

Maps to `refine_by_location_type=only_remote`.

## `searchEasyApply` (type: `boolean`):

Maps to `zipapply=1` (ZipRecruiter easy apply).

## `searchMinSalary` (type: `integer`):

Maps to `refine_by_salary`. Example prefill is illustrative.

## `searchMaxSalary` (type: `integer`):

Maps to `refine_by_salary_ceil`. Example prefill is illustrative.

## `searchStartPage` (type: `integer`):

Maps to `page` (1 = first page of results).

## `maxItems` (type: `integer`):

Maximum number of job detail records to scrape.

## `maxConcurrency` (type: `integer`):

Parallel page requests (higher = faster, more load).

## `minConcurrency` (type: `integer`):

Minimum parallel requests.

## `maxRequestRetries` (type: `integer`):

Retries per request before giving up.

## `externalApplyOnly` (type: `boolean`):

Keep only jobs that open an external apply flow. Strongest on search result pages.

## `enrichEmails` (type: `boolean`):

If enabled, tries to find a contact email for each employer by discovering the company's website (Clearbit) and reading its contact/about pages. Adds contactEmail + contactWebsite columns plus a detailed emailEnrichment object. Best-effort.

## `proxy` (type: `object`):

Specifies proxy servers that will be used by the scraper in order to hide its origin.<br><br>For details, see <a href='https://apify.com/apify/web-scraper#proxy-configuration' target='_blank' rel='noopener'>Proxy configuration</a> in README.

## `maxUnblockerRequests` (type: `integer`):

When the free proxy lanes are blocked by Cloudflare (403), the actor falls back to a paid unblocker to reliably fetch the page. This caps how many such requests a single run may make (bounds cost). Default 40.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.ziprecruiter.com/jobs-search?form=jobs-landing&search=fire+alarm+technician&location=New+York%2C+NY"
    }
  ],
  "searchJobKeyword": "software engineer",
  "searchLocation": "New York, NY",
  "searchCompany": "Acme Corp",
  "searchPostedWithinDays": 7,
  "searchRadiusMiles": 25,
  "searchEmploymentType": "all",
  "searchRemoteOnly": false,
  "searchEasyApply": false,
  "searchMinSalary": 60000,
  "searchMaxSalary": 150000,
  "searchStartPage": 1,
  "maxItems": 100,
  "maxConcurrency": 10,
  "minConcurrency": 1,
  "maxRequestRetries": 30,
  "externalApplyOnly": false,
  "enrichEmails": false,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  },
  "maxUnblockerRequests": 40
}
```

# Actor output Schema

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

No description

# 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 = {
    "startUrls": [
        {
            "url": "https://www.ziprecruiter.com/jobs-search?form=jobs-landing&search=fire+alarm+technician&location=New+York%2C+NY"
        }
    ],
    "searchJobKeyword": "software engineer",
    "searchLocation": "New York, NY",
    "searchCompany": "Acme Corp",
    "searchPostedWithinDays": 7,
    "searchRadiusMiles": 25,
    "searchMinSalary": 60000,
    "searchMaxSalary": 150000,
    "searchStartPage": 1,
    "maxItems": 100,
    "maxConcurrency": 10,
    "minConcurrency": 1,
    "maxRequestRetries": 30,
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/ziprecruiter-scraper-ppe").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 = {
    "startUrls": [{ "url": "https://www.ziprecruiter.com/jobs-search?form=jobs-landing&search=fire+alarm+technician&location=New+York%2C+NY" }],
    "searchJobKeyword": "software engineer",
    "searchLocation": "New York, NY",
    "searchCompany": "Acme Corp",
    "searchPostedWithinDays": 7,
    "searchRadiusMiles": 25,
    "searchMinSalary": 60000,
    "searchMaxSalary": 150000,
    "searchStartPage": 1,
    "maxItems": 100,
    "maxConcurrency": 10,
    "minConcurrency": 1,
    "maxRequestRetries": 30,
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

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

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

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

```

## CLI example

```bash
echo '{
  "startUrls": [
    {
      "url": "https://www.ziprecruiter.com/jobs-search?form=jobs-landing&search=fire+alarm+technician&location=New+York%2C+NY"
    }
  ],
  "searchJobKeyword": "software engineer",
  "searchLocation": "New York, NY",
  "searchCompany": "Acme Corp",
  "searchPostedWithinDays": 7,
  "searchRadiusMiles": 25,
  "searchMinSalary": 60000,
  "searchMaxSalary": 150000,
  "searchStartPage": 1,
  "maxItems": 100,
  "maxConcurrency": 10,
  "minConcurrency": 1,
  "maxRequestRetries": 30,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call memo23/ziprecruiter-scraper-ppe --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=memo23/ziprecruiter-scraper-ppe",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "ZipRecruiter Scraper — Jobs by Keyword or URL + Employer Emails",
        "description": "ZipRecruiter scraper — search jobs by keywords, location or any search URL. Full postings: salary, employment type, remote flag, company, direct apply links. Opt-in employer contact-email enrichment for recruiting lead-gen. Filters for date, radius, easy-apply. Pay per result, JSON or CSV out.",
        "version": "0.0",
        "x-build-id": "Ub76pfuCVANWtZPp9"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/memo23~ziprecruiter-scraper-ppe/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-memo23-ziprecruiter-scraper-ppe",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/memo23~ziprecruiter-scraper-ppe/runs": {
            "post": {
                "operationId": "runs-sync-memo23-ziprecruiter-scraper-ppe",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/memo23~ziprecruiter-scraper-ppe/run-sync": {
            "post": {
                "operationId": "run-sync-memo23-ziprecruiter-scraper-ppe",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "startUrls": {
                        "title": "Job search or job page URLs",
                        "type": "array",
                        "description": "One URL per row. Example: a full `jobs-search` URL with your keyword and location in the query string.",
                        "default": [],
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL of a web page",
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "searchJobKeyword": {
                        "title": "Keyword to search",
                        "type": "string",
                        "description": "Job title or skill, e.g. `nurse`, `react developer`. Maps to ZipRecruiter `search`."
                    },
                    "searchLocation": {
                        "title": "Location",
                        "type": "string",
                        "description": "City, state, region, or country, e.g. `Austin, TX` or `United States`. Maps to `location`."
                    },
                    "searchCompany": {
                        "title": "Company (optional)",
                        "type": "string",
                        "description": "Narrow results to one employer. Maps to `company`. Example below is for the form only—clear it if you want all companies."
                    },
                    "searchPostedWithinDays": {
                        "title": "Posted within (days)",
                        "type": "integer",
                        "description": "Only show jobs posted in the last N days. Maps to ZipRecruiter `days`."
                    },
                    "searchRadiusMiles": {
                        "title": "Radius (miles)",
                        "type": "integer",
                        "description": "Search radius around the location. Maps to `radius`."
                    },
                    "searchEmploymentType": {
                        "title": "Employment type",
                        "enum": [
                            "all",
                            "full_time",
                            "part_time",
                            "contract",
                            "temporary",
                            "internship"
                        ],
                        "type": "string",
                        "description": "Maps to `refine_by_employment` (employment_type:…).",
                        "default": "all"
                    },
                    "searchRemoteOnly": {
                        "title": "Remote only",
                        "type": "boolean",
                        "description": "Maps to `refine_by_location_type=only_remote`.",
                        "default": false
                    },
                    "searchEasyApply": {
                        "title": "Easy apply only",
                        "type": "boolean",
                        "description": "Maps to `zipapply=1` (ZipRecruiter easy apply).",
                        "default": false
                    },
                    "searchMinSalary": {
                        "title": "Minimum salary (optional)",
                        "type": "integer",
                        "description": "Maps to `refine_by_salary`. Example prefill is illustrative."
                    },
                    "searchMaxSalary": {
                        "title": "Maximum salary (optional)",
                        "type": "integer",
                        "description": "Maps to `refine_by_salary_ceil`. Example prefill is illustrative."
                    },
                    "searchStartPage": {
                        "title": "Results page (start)",
                        "type": "integer",
                        "description": "Maps to `page` (1 = first page of results).",
                        "default": 1
                    },
                    "maxItems": {
                        "title": "Max items",
                        "type": "integer",
                        "description": "Maximum number of job detail records to scrape.",
                        "default": 100
                    },
                    "maxConcurrency": {
                        "title": "Max concurrency",
                        "type": "integer",
                        "description": "Parallel page requests (higher = faster, more load).",
                        "default": 10
                    },
                    "minConcurrency": {
                        "title": "Min concurrency",
                        "type": "integer",
                        "description": "Minimum parallel requests.",
                        "default": 1
                    },
                    "maxRequestRetries": {
                        "title": "Max request retries",
                        "type": "integer",
                        "description": "Retries per request before giving up.",
                        "default": 30
                    },
                    "externalApplyOnly": {
                        "title": "External apply only",
                        "type": "boolean",
                        "description": "Keep only jobs that open an external apply flow. Strongest on search result pages.",
                        "default": false
                    },
                    "enrichEmails": {
                        "title": "Enrich with employer contact emails (experimental)",
                        "type": "boolean",
                        "description": "If enabled, tries to find a contact email for each employer by discovering the company's website (Clearbit) and reading its contact/about pages. Adds contactEmail + contactWebsite columns plus a detailed emailEnrichment object. Best-effort.",
                        "default": false
                    },
                    "proxy": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Specifies proxy servers that will be used by the scraper in order to hide its origin.<br><br>For details, see <a href='https://apify.com/apify/web-scraper#proxy-configuration' target='_blank' rel='noopener'>Proxy configuration</a> in README.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ],
                            "apifyProxyCountry": "US"
                        }
                    },
                    "maxUnblockerRequests": {
                        "title": "Max unblocker requests (Cloudflare fallback)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "When the free proxy lanes are blocked by Cloudflare (403), the actor falls back to a paid unblocker to reliably fetch the page. This caps how many such requests a single run may make (bounds cost). Default 40.",
                        "default": 40
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
