{
  "openapi": "3.0.1",
  "info": {
    "title": "ZipRecruiter Scraper — Jobs by Keyword or URL + Employer Emails",
    "description": "ZipRecruiter job scraper for the US, Canada, UK, Ireland, India, Germany, France and Australia: many keywords and cities per run, or any search URL. Salary, benefits, workplace type and apply links, only-new-jobs mode, run alerts and opt-in employer emails. JSON/CSV.",
    "version": "0.1",
    "x-build-id": "2Em5QSnhQozQ3rvSP"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/memo23~ziprecruiter-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-memo23-ziprecruiter-scraper",
        "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/runs": {
      "post": {
        "operationId": "runs-sync-memo23-ziprecruiter-scraper",
        "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/run-sync": {
      "post": {
        "operationId": "run-sync-memo23-ziprecruiter-scraper",
        "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. A `jobs-search` URL without a location searches the whole United States.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "searchJobKeyword": {
            "title": "Keyword to search",
            "type": "string",
            "description": "Job title or skill, e.g. `nurse`, `react developer`. Maps to ZipRecruiter `search`."
          },
          "searchKeywords": {
            "title": "More keywords (optional)",
            "type": "array",
            "description": "Search several keywords in one run. Every keyword is searched in every location, and a job listed by more than one search is saved once.",
            "items": {
              "type": "string"
            }
          },
          "search": {
            "title": "search (alias)",
            "type": "string",
            "description": "Job keyword. Alias of Search job keyword — either works."
          },
          "searchLocation": {
            "title": "Location",
            "type": "string",
            "description": "City, state, region, or country, e.g. `Austin, TX`. Leave empty to search the whole country. Maps to `location`."
          },
          "searchLocations": {
            "title": "More locations (optional)",
            "type": "array",
            "description": "Search several locations in one run, e.g. `Austin, TX`, `Denver, CO`. Every keyword is searched in every location (up to 100 searches per run).",
            "items": {
              "type": "string"
            }
          },
          "searchCountry": {
            "title": "Country",
            "enum": [
              "US",
              "CA",
              "UK",
              "IE",
              "IN",
              "DE",
              "FR",
              "AU"
            ],
            "type": "string",
            "description": "Which ZipRecruiter to search. **United States** and **Canada** search ziprecruiter.com (use a Canadian city such as `Toronto, ON`, or leave the location empty for all of Canada). **United Kingdom**, **Ireland**, **India**, **Germany**, **France** and **Australia** search ziprecruiter.co.uk, .ie, .in, .de, .fr and .com.au. Irish, Indian and German jobs are read in full. UK jobs, about half of French and a quarter of Australian jobs open on the source site, so their rows carry the search card (no full description; French cards have no snippet either). These sites have no radius, salary, experience or apply-type filter; India and Australia filter job type by full time only, France by CDI only.",
            "default": "US"
          },
          "location": {
            "title": "location (alias)",
            "type": "string",
            "description": "City, state or ZIP; leave empty to search the whole United States. Alias of Search location."
          },
          "searchCompany": {
            "title": "Company (optional)",
            "type": "string",
            "description": "Narrow results to one employer. Maps to `company`. Leave empty for all companies."
          },
          "searchPostedWithinDays": {
            "title": "Posted within (days)",
            "type": "integer",
            "description": "Only show jobs posted in the last N days. Maps to ZipRecruiter `days`."
          },
          "daysPosted": {
            "title": "daysPosted (alias)",
            "type": "integer",
            "description": "Only jobs posted within N days. Alias of Posted within days."
          },
          "searchRadiusMiles": {
            "title": "Radius (miles)",
            "type": "integer",
            "description": "Search radius around the location. Maps to `radius`."
          },
          "radiusMiles": {
            "title": "radiusMiles (alias)",
            "type": "integer",
            "description": "Search radius in miles. Alias of Search 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"
          },
          "jobType": {
            "title": "jobType (alias)",
            "type": "string",
            "description": "Employment type; 'any' is treated as all. Alias of Employment type."
          },
          "searchRemoteOnly": {
            "title": "Remote only",
            "type": "boolean",
            "description": "Maps to `refine_by_location_type=only_remote`. Same as Workplace = Remote.",
            "default": false
          },
          "remoteOnly": {
            "title": "remoteOnly (alias)",
            "type": "boolean",
            "description": "Remote jobs only. Alias of Remote only."
          },
          "searchWorkplace": {
            "title": "Workplace",
            "enum": [
              "any",
              "remote",
              "hybrid",
              "on_site"
            ],
            "type": "string",
            "description": "Remote, hybrid or on-site jobs only. Overrides **Remote only** when set. The UK and Irish sites list every job as on-site, so only On-site applies there.",
            "default": "any"
          },
          "searchExperienceLevels": {
            "title": "Experience level",
            "type": "array",
            "description": "Only jobs for these experience levels. Leave empty for all. ziprecruiter.com (US and Canada) only.",
            "items": {
              "type": "string",
              "enum": [
                "no_experience",
                "junior",
                "mid",
                "senior"
              ],
              "enumTitles": [
                "No experience",
                "Junior",
                "Mid level",
                "Senior"
              ]
            }
          },
          "searchEasyApply": {
            "title": "1-Click Apply only",
            "type": "boolean",
            "description": "Only jobs you apply to on ZipRecruiter (1-Click Apply), no redirect to the employer's site. Uses the site's own filter (`refine_by_apply_type=one_click_apply`) and each job's apply button.",
            "default": false
          },
          "searchMinSalary": {
            "title": "Minimum salary (optional)",
            "type": "integer",
            "description": "Maps to `refine_by_salary`. Leave empty for no floor."
          },
          "searchMaxSalary": {
            "title": "Maximum salary (optional)",
            "type": "integer",
            "description": "Maps to `refine_by_salary_ceil`. Leave empty for no ceiling."
          },
          "searchSortBy": {
            "title": "Sort by",
            "enum": [
              "relevance",
              "date"
            ],
            "type": "string",
            "description": "Newest first is available on the UK, Irish, Indian, German, French and Australian sites. ziprecruiter.com (US and Canada) always returns best match: use **Posted within (days)** there to get recent jobs.",
            "default": "relevance"
          },
          "searchStartPage": {
            "title": "Results page (start)",
            "type": "integer",
            "description": "Maps to `page` (1 = first page of results).",
            "default": 1
          },
          "scrapeJobDetails": {
            "title": "Open each job page (full description)",
            "type": "boolean",
            "description": "On: every job's own page is read, for the full description, validity date and apply link. Off (listing-only): rows come straight from the search results, with title, company, location, pay, workplace type, employment type, benefits, posting date, a description snippet and the apply link. Much faster. Rows have `detailsFetched: false`.",
            "default": true
          },
          "deduplicateJobs": {
            "title": "Save each job once per run",
            "type": "boolean",
            "description": "When several searches (keywords, locations, URLs) list the same job, save it once. Turn off to keep one row per search that listed it.",
            "default": true
          },
          "maxItems": {
            "title": "Max items",
            "type": "integer",
            "description": "Maximum number of jobs to save in this run. In the US and Canada, ZipRecruiter shows at most about 60 jobs per search (3 pages). With \"Search past the 60-job limit\" on, the run also searches narrower versions of a bigger search to reach this number.",
            "default": 100
          },
          "maxItemsPerSearch": {
            "title": "Max items per search",
            "minimum": 0,
            "type": "integer",
            "description": "Cap for each search (each keyword × location, or each pasted search URL), so every search of a multi-search run gets its share. 0 = no cap per search; the run still stops at Max items.",
            "default": 0
          },
          "splitLargeSearches": {
            "title": "Search past the 60-job limit",
            "type": "boolean",
            "description": "In the US and Canada, ZipRecruiter shows at most about 60 jobs per search, however many it counts. When a search counts more and Max items asks for more, the run also searches narrower versions of it (by experience level, job type, workplace, pay band and posting date) and saves each job they add once. Off: each search stops at the jobs ZipRecruiter shows.",
            "default": true
          },
          "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
          },
          "descriptionFormats": {
            "title": "Description formats",
            "type": "array",
            "description": "Which description fields each row carries: `description` (plain text), `descriptionHtml`, `descriptionMarkdown`. Default: text and HTML.",
            "items": {
              "type": "string",
              "enum": [
                "text",
                "html",
                "markdown"
              ],
              "enumTitles": [
                "Plain text",
                "HTML",
                "Markdown"
              ]
            },
            "default": [
              "text",
              "html"
            ]
          },
          "descriptionMaxLength": {
            "title": "Description max length",
            "minimum": 0,
            "type": "integer",
            "description": "Cut the text and Markdown descriptions to this many characters (on a word boundary). 0 = no limit. HTML is never cut.",
            "default": 0
          },
          "compactOutput": {
            "title": "Compact rows",
            "type": "boolean",
            "description": "Core fields only: id, title, company, location, workplace type, employment type, salary, date posted, description, URL, apply URL. For AI agents, MCP tools and light pipelines.",
            "default": false
          },
          "omitEmptyFields": {
            "title": "Leave out empty fields",
            "type": "boolean",
            "description": "Drop fields that are empty (null, empty text, empty list) from each row.",
            "default": false
          },
          "incrementalMode": {
            "title": "Only new or changed jobs",
            "type": "boolean",
            "description": "Compare every job with earlier runs of the same search. Rows get `changeType` (`new`, `updated` or `repost`) and `firstSeenAt`. A change counts once the next run still shows it, since ZipRecruiter switches between listings of the same job. The first run saves everything. The state is kept in the key-value store `ziprecruiter-incremental` in your account.",
            "default": false
          },
          "incrementalStateKey": {
            "title": "State name (optional)",
            "type": "string",
            "description": "Name of the saved state. Leave empty and each search (its URLs and filters) gets its own state automatically. Set a name to share one state between tasks or keep it across input changes."
          },
          "skipReposts": {
            "title": "Skip reposts",
            "type": "boolean",
            "description": "Skip a job whose title, company and city match a job already seen under another id (the same job posted again).",
            "default": false
          },
          "notifyWebhookSecretUrl": {
            "title": "Webhook URL",
            "type": "string",
            "description": "Receives a JSON POST when the run ends: counts, the dataset link and the first jobs (up to Max jobs per notification)."
          },
          "notifyWebhookSecretHeaders": {
            "title": "Webhook headers",
            "type": "object",
            "description": "Optional headers for the webhook POST, e.g. `{\"Authorization\": \"Bearer …\"}`. Stored encrypted."
          },
          "notifySlackSecretUrl": {
            "title": "Slack webhook URL",
            "type": "string",
            "description": "A Slack incoming webhook (https://hooks.slack.com/services/…)."
          },
          "notifyDiscordSecretUrl": {
            "title": "Discord webhook URL",
            "type": "string",
            "description": "A Discord channel webhook (Server settings → Integrations → Webhooks)."
          },
          "notifyTelegramBotToken": {
            "title": "Telegram bot token",
            "type": "string",
            "description": "From @BotFather. Needs the chat ID below."
          },
          "notifyTelegramChatId": {
            "title": "Telegram chat ID",
            "type": "string",
            "description": "The chat, group or channel to post to, e.g. `-1001234567890` or `@yourchannel`. Add the bot to it first."
          },
          "notifyMaxJobs": {
            "title": "Max jobs per notification",
            "minimum": 1,
            "maximum": 50,
            "type": "integer",
            "description": "How many jobs a message lists (1-50). The rest are in the dataset.",
            "default": 10
          },
          "notifyOnlyWhenJobsFound": {
            "title": "Notify only when jobs were found",
            "type": "boolean",
            "description": "Skip the notification when the run saved no jobs (with incremental mode: nothing new).",
            "default": false
          },
          "proxy": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Residential proxies recommended. The default works out of the box.",
            "default": {
              "useApifyProxy": true
            }
          },
          "maxUnblockerRequests": {
            "title": "Max extra retries",
            "minimum": 0,
            "type": "integer",
            "description": "Pages that fail to load are retried automatically. This caps how many extra retry requests one run may make. 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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}