# Career Site Jobs Search: 350k+ Jobs from 13k Companies, No List (`contented_catwalk/ats-jobs-search`) Actor

Search 350,000+ live jobs from 13,000+ company career sites on Greenhouse, Lever, Ashby and Workable by title, location, remote, salary and date. No company list needed: one index refreshed daily from official public job-board APIs. Direct apply links and salaries. $3 per 1,000 jobs.

- **URL**: https://apify.com/contented_catwalk/ats-jobs-search.md
- **Developed by:** [Orvix](https://apify.com/contented_catwalk) (community)
- **Categories:** Jobs, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 jobs

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

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Career Site Jobs Search: 350,000+ jobs from 13,000+ company career sites, no company list needed

**Search every live job posted on the career sites of 13,000+ companies in one run.** These companies use **Greenhouse, Lever, Ashby and Workable**. Filter by job title, location, remote, salary and posting date.

You don't need to know which companies are hiring or which applicant tracking system (ATS) they use. One index, rebuilt every day, covers them all. Type `"data engineer"` + `"New York"` and get every match across 13,000+ employers, each with a direct apply link.

### Why use it

- **No company list or board names.** Other ATS scrapers make you paste `stripe`, `notion`, `figma`… This one already knows 13,000+ boards.
- **Fresh every day.** Every board is re-polled daily. Jobs the employer has closed drop out on the next rebuild. `indexBuiltAt` on every row shows when.
- **Real salaries.** You get structured pay from the ATS plus pay ranges parsed from job descriptions. About 30% of jobs carry a salary, and you can filter by minimum annual pay.
- **Direct apply links.** Every row links to the employer's own posting, never to a job board or aggregator.
- **Clean, low-risk sources.** Only official public job-board APIs are used. No LinkedIn, no Indeed, no logins, no personal data.
- **Fast and cheap.** A typical search returns in seconds. Pay only for jobs you get.

### Pricing

**$3 per 1,000 jobs returned** (pay per event; $0.003 per job).

- Runs that match nothing cost nothing in job fees.
- Set **Max jobs** or a maximum run cost to cap your spend. The actor stops exactly at your limit.

### Input

| Field | Example | Notes |
|---|---|---|
| `keywords` | `["data engineer", "analytics engineer"]` | Matches ANY word in the title or department (whole word, so `ai` does not match "maintenance") |
| `excludeKeywords` | `["senior", "intern"]` | Drops titles containing these |
| `locations` | `["New York", "United States", "Remote"]` | Matches ANY job location |
| `remoteOnly` | `true` | Remote-flagged jobs, or jobs with "Remote" in the location |
| `postedWithinDays` | `7` | Posted (or first seen) in the last N days |
| `hasSalaryOnly` / `minAnnualSalary` / `salaryCurrency` | `true` / `150000` / `USD` | The minimum applies to yearly ranges |
| `sources` | `["greenhouse", "ashby"]` | Optional ATS filter |
| `companies` | `["stripe", "openai"]` | Optional company-name filter |
| `includeDescription` | `true` | Fetches the current full description live from the ATS (slower) |
| `maxItems` | `500` | Results are newest first. Default 500, maximum 100,000 |

Example: remote data jobs paying at least $150k posted this week:

```json
{ "keywords": ["data engineer", "data scientist"], "remoteOnly": true, "minAnnualSalary": 150000, "postedWithinDays": 7, "maxItems": 1000 }
```

### Output (one row per job)

`title, company, companyBoard, source, jobId, locations[], remote, department, employmentType, postedAt, updatedAt, listingAgeDays, firstSeenAt, lastSeenAt, salaryMin, salaryMax, salaryCurrency, salaryPeriod, salaryText, jobUrl, applyUrl, descriptionText (optional), indexBuiltAt`

A `SUMMARY` record in the run's key-value store shows how many jobs were scanned and matched, and the filters used.

### Coverage (index of 2026-10-18)

| ATS | Companies | Open jobs |
|---|---|---|
| Greenhouse | 5,583 | 189,178 |
| Lever | 2,165 | 74,169 |
| Ashby | 3,420 | 58,804 |
| Workable | 1,954 | 55,314 |
| SmartRecruiters | 4 | 5 |
| **Total** | **13,126** | **377,470** |

Counts change daily as companies open and close roles. Workday is not included.

Need a company that isn't covered? Use our per-company actor, [Greenhouse, Lever & Ashby Jobs Scraper](https://apify.com/contented_catwalk/greenhouse-lever-ashby-jobs), with its board name.

### Use cases

- Job boards and newsletters backfilling niche listings (remote, AI, climate, fintech, by city)
- AI job-search, resume and auto-apply apps that need a fresh jobs feed
- Recruiters and sales teams watching who is hiring for a role across thousands of employers
- Labor-market, salary-transparency and hiring-trend research

### FAQ

**Is this legal?** The data comes from the job-board APIs that the ATS vendors publish for public use. For example, Greenhouse says: "Job Board data is publicly available, so authentication is not required." There is no login and no personal data. You are responsible for how you use the results.

**How fresh is it?** The index is rebuilt daily, and `indexBuiltAt` shows the build time. Use `includeDescription` for live descriptions.

**Duplicates?** Within a run, rows are unique by apply URL.

**Why is my run empty?** Your filters matched nothing. Try fewer keywords or a broader location such as `"United States"`.

### Credits

The company board list was seeded in part from the **LastRound AI ATS Company Directory** ([LastRound AI](https://lastroundai.com/featured-on), [GitHub](https://github.com/fyrosofttech/lastroundai-hiring-data), DOI [10.6084/m9.figshare.33154145](https://doi.org/10.6084/m9.figshare.33154145.v1)), licensed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/). Also from the CC0 [job-board-directory](https://kalebconfer-sys.github.io/job-board-directory/) and the MIT-licensed [africa-ats-directory](https://github.com/Thelastpoet/africa-ats-directory). Job data is fetched by us directly from each vendor's public job-board API.

# Actor input Schema

## `keywords` (type: `array`):

Return jobs whose title (or department) contains ANY of these words, e.g. "data engineer", "product manager". Leave empty for all jobs.

## `excludeKeywords` (type: `array`):

Drop jobs whose title contains any of these, e.g. "intern", "senior".

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

Match if any job location contains one of these, e.g. "New York", "United States", "London", "Remote".

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

Only jobs flagged remote by the employer, or with "Remote" in a location.

## `postedWithinDays` (type: `integer`):

Only jobs posted (or first seen by the index) in the last N days. 0 = any.

## `hasSalaryOnly` (type: `boolean`):

Only jobs that carry a salary or pay range.

## `minAnnualSalary` (type: `integer`):

Keeps yearly salaries whose top of range is at least this (in the currency below).

## `salaryCurrency` (type: `string`):

Currency used by the minimum annual salary filter, e.g. USD, EUR, GBP.

## `sources` (type: `array`):

Leave empty for all. SmartRecruiters coverage is minimal (a few companies).

## `companies` (type: `array`):

Optional: only companies whose name or board contains one of these.

## `includeDescription` (type: `boolean`):

Fetches the fresh description from the company's ATS for each returned job. Slower.

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

Newest first. You pay per job returned.

## `indexUrl` (type: `string`):

Leave empty.

## `manifestUrl` (type: `string`):

Leave empty.

## `outputToKeyValueStore` (type: `boolean`):

For API callers using run-sync: jobs are saved as one JSON record (OUTPUT) instead of dataset rows. Same price per job.

## Actor input object example

```json
{
  "keywords": [
    "data engineer"
  ],
  "remoteOnly": false,
  "hasSalaryOnly": false,
  "salaryCurrency": "USD",
  "includeDescription": false,
  "maxItems": 500,
  "outputToKeyValueStore": false
}
```

# Actor output Schema

## `jobs` (type: `string`):

One row per job, newest first, with apply link and salary when available.

## `summary` (type: `string`):

Jobs scanned, matched and delivered, index build time and filters.

# 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 = {
    "keywords": [
        "data engineer"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("contented_catwalk/ats-jobs-search").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 = { "keywords": ["data engineer"] }

# Run the Actor and wait for it to finish
run = client.actor("contented_catwalk/ats-jobs-search").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "keywords": [
    "data engineer"
  ]
}' |
apify call contented_catwalk/ats-jobs-search --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,contented_catwalk/ats-jobs-search"
        }
    }
}
```

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

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/Ty7HyIec3vHV3oZMg/builds/RTJu7RuhLGmbJdOEv/openapi.json
