{
  "openapi": "3.0.1",
  "info": {
    "title": "ZipRecruiter Scraper - Jobs, Salaries & Companies",
    "description": "From $1/1K. Scrape ZipRecruiter jobs with titles, companies, salaries, locations, benefits, apply URLs and full descriptions. Search with filters or paste ZipRecruiter URLs directly, with automatic pagination and simple pay-per-result pricing.",
    "version": "1.0",
    "x-build-id": "cCK0FtWQ5TvXjMMbq"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/abotapi~ziprecruiter-com-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-abotapi-ziprecruiter-com-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/abotapi~ziprecruiter-com-scraper/runs": {
      "post": {
        "operationId": "runs-sync-abotapi-ziprecruiter-com-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/abotapi~ziprecruiter-com-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-abotapi-ziprecruiter-com-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",
        "required": [
          "mode"
        ],
        "properties": {
          "mode": {
            "title": "1. Search mode",
            "enum": [
              "search",
              "url"
            ],
            "type": "string",
            "description": "Search mode = pick keywords + location + filters below. URL mode = paste any ziprecruiter.com search or job URL refined in your browser.",
            "default": "search"
          },
          "queries": {
            "title": "Keywords",
            "type": "array",
            "description": "Free-text search terms (e.g. \"software engineer\", \"registered nurse\", \"data analyst\"). One scrape per keyword. Leave empty to browse without a keyword filter.",
            "items": {
              "type": "string"
            }
          },
          "location": {
            "title": "Location (optional)",
            "type": "string",
            "description": "City + state, ZIP, or \"Remote\". Examples: \"New York, NY\", \"Chicago, IL\", \"94103\", \"Remote\". Leave empty to search nationwide."
          },
          "datePosted": {
            "title": "Date posted",
            "enum": [
              "any",
              "1",
              "5",
              "10",
              "30"
            ],
            "type": "string",
            "description": "Only return jobs posted within this window. \"Any time\" walks the unfiltered SERP.",
            "default": "any"
          },
          "employmentType": {
            "title": "Employment type",
            "enum": [
              "any",
              "full_time",
              "part_time",
              "contract",
              "temporary",
              "internship"
            ],
            "type": "string",
            "description": "Filter by employment scope. \"Any\" walks the unfiltered SERP.",
            "default": "any"
          },
          "remoteOnly": {
            "title": "Remote jobs only",
            "type": "boolean",
            "description": "Only return jobs flagged as remote.",
            "default": false
          },
          "minSalary": {
            "title": "Minimum annual salary (USD)",
            "minimum": 0,
            "type": "integer",
            "description": "Only return jobs whose advertised pay is at or above this annual figure. Leave at 0 for no salary floor.",
            "default": 0
          },
          "radius": {
            "title": "Search radius (miles)",
            "minimum": 0,
            "maximum": 200,
            "type": "integer",
            "description": "Distance around the location to include. Leave at 0 to use ZipRecruiter's default radius.",
            "default": 0
          },
          "skipSponsored": {
            "title": "Skip sponsored placements",
            "type": "boolean",
            "description": "Drop sponsored / promoted job cards. Applied as a client-side filter.",
            "default": false
          },
          "urls": {
            "title": "Search URLs (URL mode)",
            "type": "array",
            "description": "One or more ziprecruiter.com URLs. Supported: a search URL (…/jobs-search?search=software+engineer&location=Remote), a legacy keyword path (…/Jobs/Software-Engineer, mapped to a search), or a single job URL (…/c/Raytheon/Job/Software-Engineer-II-(Onsite)/-in-Tucson,AZ?jid=36f7f16aec6bade9). Multi-URL supported; each search URL pages forward independently. Remote and minimum-salary facets in a pasted URL are honoured. Leaving this field untouched in URL mode scrapes one example per shape.",
            "default": [
              "https://www.ziprecruiter.com/jobs-search?search=software+engineer&location=Remote",
              "https://www.ziprecruiter.com/Jobs/Software-Engineer",
              "https://www.ziprecruiter.com/c/Raytheon/Job/Software-Engineer-II-(Onsite)/-in-Tucson,AZ?jid=36f7f16aec6bade9"
            ],
            "items": {
              "type": "string"
            }
          },
          "maxPages": {
            "title": "Max pages per search",
            "minimum": 0,
            "type": "integer",
            "description": "How many SERP pages to walk per keyword × location combination (or per pasted URL). Each page returns up to 20 listings. Leave empty to walk every result page (bounded by `maxListings` and ZipRecruiter's own result total)."
          },
          "maxListings": {
            "title": "Max listings (total)",
            "minimum": 0,
            "maximum": 1000000,
            "type": "integer",
            "description": "Stop after this many listings across all searches. 0 = no cap (still bounded by maxPages).",
            "default": 20
          },
          "fetchDetails": {
            "title": "Fetch detail pages (richer data)",
            "type": "boolean",
            "description": "When ON, also fetch each job's detail page for the full HTML description, structured street address, industry, valid-through date, and verified salary. SERP cards already carry id, title, company, location, salary, employment type, benefits, snippet, and posted date, so most feeds work great with this OFF (faster and cheaper). Default OFF.",
            "default": false
          },
          "maxItemsPerSearch": {
            "title": "Max listings per search",
            "minimum": 0,
            "type": "integer",
            "description": "Extra ceiling for each keyword or each pasted link, on top of the even share of Max listings. 0 = no extra ceiling.",
            "default": 0
          },
          "workplace": {
            "title": "Workplace type (client-side screen)",
            "enum": [
              "any",
              "remote",
              "hybrid",
              "onsite"
            ],
            "type": "string",
            "description": "Keep only jobs the site tags as remote, hybrid or on-site. Applied to the loaded results, so a narrow choice can return fewer jobs than Max listings; the run is then not treated as a complete read of the search. 'On-site' also keeps jobs that carry no workplace tag.",
            "default": "any"
          },
          "maxSalary": {
            "title": "Maximum annual salary (USD)",
            "minimum": 0,
            "type": "integer",
            "description": "Drop jobs whose lowest advertised annual pay is above this figure. Only jobs paid per year are screened; hourly, weekly and unpriced jobs are kept. 0 = off.",
            "default": 0
          },
          "externalApplyOnly": {
            "title": "Only jobs that apply on the employer's site",
            "type": "boolean",
            "description": "Keep only jobs whose apply button leads to an external employer or partner page (externalApplyUrl is set). Applied to the loaded results.",
            "default": false
          },
          "descriptionMaxLength": {
            "title": "Shorten descriptions to N characters",
            "minimum": 0,
            "type": "integer",
            "description": "Cut descriptionText, description and descriptionMarkdown to this many characters. descriptionHtml is set to null when it is longer than the limit (a cut HTML string would be invalid). Does not change what counts as UPDATED. 0 = full text.",
            "default": 0
          },
          "omitEmptyFields": {
            "title": "Leave out empty fields",
            "type": "boolean",
            "description": "Drop fields whose value is null, empty text or an empty list from each row, for a smaller dataset. Does not change what counts as UPDATED.",
            "default": false
          },
          "proxy": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "ZipRecruiter requires US residential routing (Datacenter exit IPs are rejected by the upstream edge). The default below works on Apify Starter and higher. Free plans without residential access can paste their own residential proxy URLs in this field."
          },
          "resumeFromRunId": {
            "title": "Resume from a previous run (optional)",
            "type": "string",
            "description": "Paste a previous run ID or dataset ID to continue a full-catalogue walk across separate runs. Listings already collected there (matched by job id) are skipped, so this run only saves the new ones. Leave empty for a normal fresh run."
          },
          "incrementalMode": {
            "title": "Incremental changes for scheduled runs",
            "type": "boolean",
            "description": "Turn this on for daily or recurring monitoring of the same search. The first run returns every matching job as NEW. Later runs return only NEW, UPDATED and REAPPEARED jobs; unchanged jobs are neither returned nor billed. Every returned row gets changeType, changedFields, firstSeenAt and lastSeenAt. A job counts as UPDATED when any field other than these ignored ones changed: scrapedAt, pageNumber, sponsored, inputUrl, postedAt, datePosted, listingKey, companyLogo (the scrape time, the results page the job landed on, the promoted flag, the start link, the posted time, the listing tracking key and the logo link change without any real change to the job). Everything else counts, for example title, salary, location, description, benefits, apply link, so a changed salary or description returns the job as UPDATED with the field names in changedFields. Ignored fields are still returned in each row. Add your own with the ignore list at the end of this section. State is kept per search (mode, queries, location, filters, detail setting, URLs), never per item limit or page limit. Use State key to name a campaign. To continue one interrupted run instead, use Resume from a previous run above.",
            "default": false
          },
          "stateKey": {
            "title": "State key (optional, incremental mode only)",
            "type": "string",
            "description": "Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently configured runs. Leave empty to derive a key from the search settings, so different searches never mix state."
          },
          "emitUnchanged": {
            "title": "Emit unchanged jobs (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. Turn on to also return jobs that have not changed since the last run, marked UNCHANGED. These rows are delivered and billed like any other row, so leave it off unless you want the full snapshot every run.",
            "default": false
          },
          "emitExpired": {
            "title": "Emit expired jobs (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. Turn on to also return jobs seen in a previous run that are no longer found, marked EXPIRED. Only produced after a run that read the whole search up to the last page the site reports: not when Max listings or Max pages stopped it, not for a pasted single job link or a link that starts after page 1, not when any filter (sponsored, salary, employment type) removed jobs, not with Resume, and not when a page or detail page failed. These rows are delivered and billed like any other row, and they count toward Max listings: any beyond it are reported on a later run.",
            "default": false
          },
          "ignoreFieldsForChanges": {
            "title": "Ignore fields when detecting changes (incremental mode only)",
            "type": "array",
            "description": "Output field names that should NOT make a job count as UPDATED, even when they changed. Always ignored: scrapedAt, pageNumber, sponsored, inputUrl, postedAt, datePosted, listingKey, companyLogo (listed here so you know; you do not need to add them). A name without a dot matches that field at any nesting depth; a dotted name matches from the top of the row. Ignored fields are still returned in the output.",
            "items": {
              "type": "string"
            }
          },
          "mcpConnectors": {
            "title": "Pipe results into your apps (optional)",
            "type": "array",
            "description": "Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify → Settings → Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON — the complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com)."
          },
          "notionParentPageUrl": {
            "title": "Notion parent page (Notion connector only)",
            "type": "string",
            "description": "URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors."
          },
          "maxNotifyListings": {
            "title": "Max items to export per connector",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Cap on items written to each connector per run. Does not affect the dataset.",
            "default": 50
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}