# Career Site Job Search: 12,000+ Companies (`toowettodrip/career-site-job-search`) Actor

Search 400,000+ open jobs from 12,000+ company career sites by keyword, place, remote and date. No company links needed. Clean rows with title, location, pay range, dates and apply link. Rebuilt daily from Greenhouse, Lever, Ashby and Workable job boards.

- **URL**: https://apify.com/toowettodrip/career-site-job-search.md
- **Developed by:** [Cameron Causey](https://apify.com/toowettodrip) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 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/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 Job Search

Search open jobs across thousands of company career sites with a keyword. No company links needed.

Type what you are looking for, such as `data engineer`, `"account executive"` or `nurse`, add a place or tick remote if you like, and get back one clean row per matching job, newest first. The index holds more than 400,000 open jobs read straight from the career sites of more than 12,000 companies, and it is rebuilt every day.

### Where the jobs come from

Thousands of companies run their careers page on Greenhouse, Lever, Ashby or Workable. Each of those systems publishes a company's open jobs as a public list, with no login. Once a day this tool's index reads those public lists for every company in its directory and records each open job's title, place, dates, pay range and links. Your search runs against that index, which is why it answers in seconds.

The run's status line tells you how many jobs and companies the index held and how many hours ago it was rebuilt.

### What you get

One row per job, with the same fields whichever system the company uses:

- company, job title, department and team
- location, every other listed location, country
- remote or not, and the workplace type (remote, hybrid, on-site) when the company states it
- job type (full-time, internship and so on)
- date posted, and date updated when the system gives one
- link to the job and link to apply
- pay range when the company publishes one: lowest, highest, currency and period
- optionally, the full description as plain text and as HTML (see "Live check" below)

### How to use it

1. **Keywords.** One search per line. A job is kept when its title matches at least one line.
   - `data engineer` finds titles that contain both words in any order: "Senior Data Engineer" and "Engineer, Data Platform".
   - `"machine learning"` in double quotes finds that exact phrase.
   - Matching is on whole words, so `java` does not match "JavaScript". Capitals and accents do not matter.
   - Leave it empty to get every title.
2. **Narrow it down (optional).** Leave out titles with certain words, keep only certain places, only remote jobs, or only jobs posted in the last N days. You can also search only named companies, or cap how many jobs any one company contributes.
3. **Set the maximum number of jobs.** The newest matching jobs come first, with at most 5 from any one company unless you change that. You pay only for jobs returned.
4. **Run it.** Results appear in the dataset, ready to export as JSON, CSV or Excel, or to read through the API.

#### Places

Places are written the way each company writes them: "New York, NY", "NYC", "Remote - US", "Germany". List the variants you care about, one per line, for example `United States`, `USA` and `US`. A place matches as whole words, so `US` does not match "Australia".

#### Live check and descriptions

Switch on **Check each job live and add the full description** and the tool reads the career site of each matching company during your run. That adds the full description and leaves out any job that has closed since the index was last rebuilt. It takes roughly a second per company, so use it with a maximum number of jobs.

#### Only what is new

Switch on **Only jobs I have not been given before** and put the search on a daily schedule. The first run returns everything that matches. Each later run returns only jobs it has not handed you before for that same search, so you receive, and pay for, just the new openings.

### Example result

```json
{
  "company": "Ramp",
  "source": "ashby",
  "companyId": "ramp",
  "id": "34413f8d-26bf-4bbc-8ade-eb309a0e2245",
  "title": "Security Engineer, Cloud",
  "department": "Engineering",
  "team": "Backend",
  "location": "New York, NY (HQ)",
  "allLocations": ["New York, NY (HQ)", "Remote (Canada)"],
  "country": "USA",
  "remote": true,
  "workplaceType": "hybrid",
  "employmentType": "FullTime",
  "postedAt": "2026-04-07T17:12:35.753Z",
  "updatedAt": null,
  "url": "https://jobs.ashbyhq.com/ramp/34413f8d-26bf-4bbc-8ade-eb309a0e2245",
  "applyUrl": "https://jobs.ashbyhq.com/ramp/34413f8d-26bf-4bbc-8ade-eb309a0e2245/application",
  "salaryMin": 211400,
  "salaryMax": 290600,
  "salaryCurrency": "USD",
  "salaryInterval": "1 YEAR",
  "salaryText": "$211.4K - $290.6K",
  "liveChecked": false,
  "scrapedAt": "2026-10-08T05:40:00.000Z"
}
```

`scrapedAt` is when that company's career site was last read: during the daily index build, or during your run when the live check is on (`liveChecked: true`). Fields a hiring system does not provide come back as `null`. Greenhouse and Workable do not publish pay as separate numbers, and Greenhouse gives the department only with the live check on.

### Price

You pay per job returned: **$1.50 per 1,000 jobs**, plus a start fee of a fraction of a cent per run. A search that returns 100 jobs costs about $0.15. Jobs your filters remove are not charged, and with the only-new switch on, jobs you have already received are not charged again. If you set a spending limit for a run, the tool stops when it is reached and tells you so.

### What it does not do

- It covers companies whose careers page runs on Greenhouse, Lever, Ashby or Workable and that are in its directory. It is not every job on the internet, and it leans towards technology companies and startups, which use these systems most.
- Some of the career sites belong to staffing firms and to chains that post hundreds of near-identical ads. To keep them from filling your list, each company contributes at most 5 jobs unless you change **Maximum jobs per company** (0 means no limit).
- Keywords search the job title, not the description text.
- The index is rebuilt once a day, so a job posted this morning may appear tomorrow, and a job filled today may still show until the next rebuild. Use the live check when that matters.
- It reads only the public job lists that the hiring systems publish. It does not log in anywhere and does not get around any block.
- It does not collect recruiter names, email addresses or any other personal details.

Job descriptions are written by the employers and remain theirs. Use them for your own search, research or analysis. If you plan to republish them, check that you are allowed to.

### Common questions

**A company I expect is missing.** It may have no open roles today, or its careers page may run on a different system, or it may not be in the directory yet. Open an issue on the Issues tab with the company's careers page address and it can be added.

**Can I give it my own list of company career pages?** Use the companion tool, [Career Page Jobs Scraper](https://apify.com/toowettodrip/career-page-jobs), which reads any Greenhouse, Lever, Ashby or Workable career page you paste, live.

**How fresh is the data?** The status line of every run says how many hours ago the index was rebuilt. With the live check on, each returned job was confirmed open during your run.

**Something is wrong or missing.** Open an issue on the Issues tab with the search you ran. Issues are answered there.

This tool is not affiliated with or endorsed by Greenhouse, Lever, Ashby or Workable.

# Actor input Schema

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

One search per line. A job is kept if its title matches at least one line. All words on a line must be in the title, in any order: data engineer finds "Senior Data Engineer" and "Engineer, Data Platform". Put a line in double quotes for the exact phrase: "machine learning". Whole words only, so java does not match JavaScript. Leave empty for every title.

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

Drop a job if its title matches any of these lines. Same rules as above. For example: senior, intern, "vice president".

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

Keep a job only if one of its listed places contains one of these, as whole words. For example: New York, Germany, London, Remote. Places are written the way each company writes them, so add the variants you care about (United States, USA, US). Leave empty for every place.

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

Keep only jobs the company marks as remote.

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

Keep only jobs published in the last N days. 0 keeps every job.

## `maxResults` (type: `integer`):

The newest matching jobs are returned first, up to this number. 0 means no limit. You pay only for jobs returned.

## `maxPerCompany` (type: `integer`):

Keep at most this many matching jobs from any one company, newest first. This stops staffing firms and chains with hundreds of near-identical ads from filling your list. Set 0 for no limit, for example when you want every opening at the companies you named.

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

Company names, one per line, for example Stripe or Hugging Face. Leave empty to search every company in the index.

## `systems` (type: `array`):

Search only companies whose career site runs on the chosen systems. Leave empty for all four.

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

Reads the career site of each matching company during the run. Adds the full job description as plain text and leaves out jobs that have closed since the index was last rebuilt. Adds roughly a second per company, so use it together with a maximum number of jobs.

## `includeDescriptionHtml` (type: `boolean`):

Adds the original formatted description. Only used when the live check is on.

## `onlyNewSinceLastRun` (type: `boolean`):

Remembers which jobs it has already returned to you for this exact search and returns only the others. Put the search on a daily schedule to receive just the new openings each day. The first run returns everything that matches.

## Actor input object example

```json
{
  "keywords": [
    "software engineer"
  ],
  "remoteOnly": false,
  "postedWithinDays": 0,
  "maxResults": 100,
  "maxPerCompany": 5,
  "includeDescription": false,
  "includeDescriptionHtml": false,
  "onlyNewSinceLastRun": false
}
```

# Actor output Schema

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

The matching jobs, newest first.

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

How many jobs matched, how many were returned, and when the job index was last rebuilt.

# 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": [
        "software engineer"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("toowettodrip/career-site-job-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": ["software engineer"] }

# Run the Actor and wait for it to finish
run = client.actor("toowettodrip/career-site-job-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": [
    "software engineer"
  ]
}' |
apify call toowettodrip/career-site-job-search --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,toowettodrip/career-site-job-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/X2BwplyPWfJDQDb6L/builds/CyaOOKmBQkE64itYC/openapi.json
