# HireHeat Jobs — Career Site Job Listings from 12,000+ Companies (`cybermax/career-site-jobs`) Actor

Search open jobs straight from 12,000+ company career sites (Greenhouse, Ashby, Workable, SmartRecruiters, Recruitee; Lever via company domains). Keyword, location, remote and date filters, newest first, salary where posted. Monitor mode returns only new jobs for daily job alerts. $0.002 per job.

- **URL**: https://apify.com/cybermax/career-site-jobs.md
- **Developed by:** [CyberMax](https://apify.com/cybermax) (community)
- **Categories:** Jobs, AI, Lead generation
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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

## HireHeat Jobs — Career Site Job Listings from 12,000+ Companies

**Search job listings straight from company career sites**: 12,000+ employers' public job boards on Greenhouse, Ashby, Workable, SmartRecruiters and Recruitee (plus Lever for any company you name), filtered by title keywords, location, remote and posted date, newest first. One clean JSON schema for every job, ready for a job board, a lead list or an AI agent.

**$0.002 per job returned + $0.02 per search.** 1,000 jobs cost $2.02; a search that matches nothing costs 2 cents.

**First try:** the prefilled input (`engineer` jobs at one company, `vercel`, max 3 jobs) reads one career site in about a second of work plus container start and costs **$0.026** ($0.02 search + 3 × $0.002).

### Why HireHeat Jobs

- **Straight from the source.** Jobs come from each employer's own applicant tracking system, not from reposts on aggregators, so apply links go to the real posting and closed jobs disappear when the employer closes them.
- **12,331 company career sites, validated.** The built-in directory was collected from the public web and every board was checked against its live ATS API (September 2026): 4,047 Greenhouse, 2,716 Ashby, 2,712 Workable, 1,053 SmartRecruiters and 1,803 Recruitee boards, about 468,000 open jobs at build time.
- **Job alerts built in.** Turn on monitor mode (`newOnly`), schedule the Actor daily, and each run returns only postings you haven't seen.
- **Six times cheaper per job** than the best-known career-site job API on the Apify Store ($0.012 per job at the time of writing).

### Example: input

```json
{
  "keywords": ["data engineer", "analytics engineer"],
  "locations": ["United States", "Remote"],
  "postedWithinDays": 14,
  "maxJobs": 200
}
```

A real run of this input on Apify (23 Sep 2026) read 8,852 career sites in 5 minutes and returned 176 matching jobs, newest first. A search for 9 AI/ML job titles posted in the last 7 days returned 265 jobs.

### Ready-made inputs (first try in one click)

**No account yet?** See real results first on the free demo page: [AI & ML jobs posted this week](https://huggingface.co/spaces/shaw276/ai-jobs-this-week).

Paste one into the **JSON** tab of the input form (or send it to the API) and press **Start**. Each is sized so the first run is quick and cheap; you pay only for results (Apify's compute is included in the price).

| Preset | What you get | Cost |
|---|---|---|
| 3 jobs at one company | the 3 newest matching jobs with apply links | $0.026 (1 search + 3 jobs; the lowest this tool goes) |
| Designers at 3 companies | up to 3 design jobs across the 3 boards | $0.026 or less |
| Sales jobs posted in the last 30 days (3 companies) | the 5 newest matching jobs, newest first | $0.03 |

**3 jobs at one company**

```json
{"keywords": ["engineer"], "companyNames": ["vercel"], "maxJobs": 3}
```

**Designers at 3 companies**

```json
{"keywords": ["designer"], "companyNames": ["notion", "figma", "linear"], "maxJobs": 3}
```

**Sales jobs posted in the last 30 days (3 companies)**

```json
{"keywords": ["sales"], "companyNames": ["notion", "stripe", "ramp"], "postedWithinDays": 30, "maxJobs": 5}
```

Same thing from a script (returns the results directly):

```bash
curl -s -X POST "https://api.apify.com/v2/acts/cybermax~career-site-jobs/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H 'content-type: application/json' -d '{"keywords": ["engineer"], "companyNames": ["vercel"], "maxJobs": 3}'
```

### Example: one job in the output

```json
{
  "title": "Principal Data Engineer",
  "company": "AvidXchange, Inc.",
  "location": "Charlotte, North Carolina, United States",
  "remote": false,
  "department": "Engineering",
  "team": null,
  "employmentType": null,
  "salary": null,
  "postedAt": "2026-09-23T15:56:04.000Z",
  "daysAgo": 0,
  "url": "https://job-boards.greenhouse.io/avidxchangeinc/jobs/5234647007",
  "ats": "greenhouse",
  "boardSlug": "avidxchangeinc",
  "boardUrl": "https://boards.greenhouse.io/avidxchangeinc",
  "jobId": "greenhouse:avidxchangeinc:5234647007",
  "matchedKeywords": ["data engineer"]
}
```

`salary` is filled when the employer publishes it (common on Ashby, Lever and Recruitee boards). The run's `SUMMARY` record in the key-value store says how many boards were searched and how many jobs matched in total.

### Inputs

| Field | What it does |
|---|---|
| `keywords` | Title contains any of these words or phrases (whole words, case-insensitive). Empty = all jobs. |
| `excludeKeywords` | Drop titles containing any of these (e.g. `intern`, `manager`). |
| `locations` | Location contains any of these. `United States`/`US`/`USA`, `UK`, `New York`/`NYC`, `San Francisco`/`Bay Area` and `Germany` match their common spellings. `Remote` also matches jobs flagged remote. |
| `remoteOnly` | Only jobs marked remote. |
| `postedWithinDays` | Only jobs first posted in the last N days (undated jobs are left out). |
| `maxJobs` | Newest jobs first; default 500. |
| `newOnly` + `stateKey` | Monitor / job-alert mode: return only jobs this search hasn't returned before (see below). `monitor` + `monitorKey` are accepted as aliases. |
| `ats` | Limit to some platforms. Default: Greenhouse, Ashby, Workable, SmartRecruiters. Recruitee (1,803 mostly European employers) is opt-in: it rate-limits cloud servers, so it makes searches slower. |
| `companyNames` | Only directory companies whose name contains one of these. |
| `companies` | Search these companies instead of the directory: domains (`ramp.com`) or board URLs (`https://jobs.lever.co/palantir`). The Actor finds each company's board itself, including Lever. |
| `maxRunSecs` | Time budget, default 300 s. Biggest employers are read first; when the budget runs out the Actor returns what it found and the `SUMMARY` says how many (small) boards were left unread. At the default, the unread boards hold about 1.5% of the directory's jobs, mostly small Workable boards, which rate-limit cloud servers. |
| `maxBoards` | Search an evenly spread sample of N boards: a quick, cheap test. |

### Pricing: how much does it cost to scrape career site jobs?

| Event | Price |
|---|---|
| Search (once per run, across all 12,000+ career sites) | $0.02 |
| Job returned | $0.002 |

1,000 jobs cost $2.02. A search that matches nothing costs 2 cents, and in monitor mode jobs you've already received are neither returned nor charged. No start fee and no compute charges on top. Set a maximum charge per run in Apify to cap any run.

### Monitor mode: job alerts

Set `"newOnly": true` (or `"monitor": true`) and run the same search on a schedule. HireHeat Jobs remembers every `jobId` it returned for this search (in a key-value store named `hireheat-jobs-state` in your Apify account, keyed by `stateKey` or by the filters) and each later run returns **only postings it hasn't returned before**, each marked:

```json
{ "title": "…", "company": "…", "jobId": "greenhouse:vercel:6201179004", "change": "new" }
```

The first run returns every match as `"new"`. Already-seen jobs are not returned and not charged, so a daily alert costs $0.02 plus $0.002 per new job. A job posting is either new or already seen (there is no "changed" state). Jobs cut off by `maxJobs` or a charge limit are not marked as seen, so they come back next run. Seen IDs are forgotten after 90 days. The run's `SUMMARY` adds `newJobs` and `alreadySeenJobs`.

### Run it on a schedule

In Apify Console: **Schedules → Create new → cron** `0 8 * * *` (daily at 8:00) → **Add Actor** → HireHeat Jobs with your saved input (or a saved task) and `"newOnly": true`. Or with the API:

```http
POST https://api.apify.com/v2/schedules?token=YOUR_TOKEN
{
  "name": "ml-jobs-daily",
  "cronExpression": "0 8 * * *",
  "timezone": "America/New_York",
  "isEnabled": true,
  "actions": [{
    "type": "RUN_ACTOR",
    "actorId": "cybermax/career-site-jobs",
    "runInput": {
      "body": "{\"keywords\": [\"machine learning engineer\"], \"locations\": [\"United States\", \"Remote\"], \"newOnly\": true, \"stateKey\": \"ml-us\"}",
      "contentType": "application/json"
    }
  }]
}
```

Monitor mode makes daily runs cheap: you pay only for new postings. To get the new jobs by email or in Slack, add a webhook or email notification on **Run succeeded** (Actor → Integrations).

### Integrations

**Make:** Apify app → "Run an Actor" (`cybermax/career-site-jobs`, input JSON, wait for finish) → "Get Dataset Items".

**Zapier:** Apify app → "Run Actor" action, or the "Finished Actor Run" trigger on your schedule → a Sheets / Slack / ATS step.

**n8n:** Apify node ("Run Actor and get dataset"), or an HTTP Request node:

```
POST https://api.apify.com/v2/acts/cybermax~career-site-jobs/run-sync-get-dataset-items?token=YOUR_TOKEN
{"keywords": ["data engineer"], "remoteOnly": true, "postedWithinDays": 7, "maxJobs": 100}
```

**Google Sheets:** Apify's Google Sheets integration, or in a cell:

```
=IMPORTDATA("https://api.apify.com/v2/acts/cybermax~career-site-jobs/runs/last/dataset/items?format=csv&fields=title,company,location,postedAt,url&token=YOUR_TOKEN")
```

**Python:**

```python
from apify_client import ApifyClient
client = ApifyClient("YOUR_TOKEN")
run = client.actor("cybermax/career-site-jobs").call(run_input={"keywords": ["data engineer"], "locations": ["Remote"], "maxJobs": 100})
for job in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(job["title"], job["company"], job["url"])
```

**JavaScript:**

```js
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('cybermax/career-site-jobs').call({ keywords: ['data engineer'], newOnly: true });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

**AI agents (MCP):** call it through Apify's MCP server, `https://mcp.apify.com/?tools=cybermax/career-site-jobs` (header `Authorization: Bearer <your Apify token>`). Tool input is the JSON above; output is a flat list of jobs with stable `jobId`s, so an agent can answer "who is hiring remote Rust engineers this week?" in one call. Claude Desktop / Cursor config:

```json
{ "mcpServers": { "hireheat-jobs": { "url": "https://mcp.apify.com/?tools=cybermax/career-site-jobs", "headers": { "Authorization": "Bearer YOUR_APIFY_TOKEN" } } } }
```

### When NOT to use HireHeat Jobs

- You need LinkedIn, Indeed or Glassdoor listings: this reads company career sites only.
- You need companies on Workday, iCIMS, Taleo or other enterprise ATSs: they aren't covered yet.
- You want one company's hiring *trend* (new roles per week, functions, seniority) rather than job rows: use [HireHeat: Company Hiring Signals](https://apify.com/cybermax/hiring-signals), which also has a monitor mode.
- You need the full job description text: the output has title, location, department, salary and the apply link, not the description body.

### FAQ

**Which job boards does it cover?** Company career sites on Greenhouse, Ashby, Workable, SmartRecruiters and Recruitee (12,331 validated boards in the built-in directory), plus Lever and any of those platforms for companies you name in `companies`.

**Is there a Greenhouse or Lever jobs API?** Each ATS publishes a public JSON feed per employer. HireHeat Jobs searches all of them at once and returns one schema, so you don't need to know each company's board slug.

**How fresh are the jobs?** They are read live from each employer's board during the run, so closed jobs are gone and new ones appear the minute the employer posts them.

**How do I get daily job alerts?** Set `"newOnly": true`, save the input as a task, and schedule it daily (see below). Each run returns only jobs you haven't received.

**Can an AI agent use it?** Yes, through Apify's MCP server (`https://mcp.apify.com/?tools=cybermax/career-site-jobs`), and it's in the official MCP Registry.

**Why didn't a big company show up?** It may use Workday, iCIMS or another ATS that isn't covered yet, or its board isn't in the directory: pass its domain in `companies` and the Actor looks for the board itself.

### Also from CyberMax

- [HireHeat](https://apify.com/cybermax/hiring-signals): one hiring summary per company domain (open and new roles, functions, seniority), with hiring-spike alerts.
- [Hollerdex](https://apify.com/cybermax/website-contacts): emails, phones and socials for the companies you find.
- [DomainDNA](https://apify.com/cybermax/domain-intel): what a hiring company runs on (tech stack, email security, domain age).
- [Logolark](https://huggingface.co/spaces/shaw276/saas-logos-brand-colors?soon=logo-finder): company logos and favicons for your job board.

All tools: [Boardroom Buys](https://apify.com/cybermax/sec-insider-tracker) · [SnapScout](https://apify.com/cybermax/website-screenshot) · [Swellmeter](https://apify.com/cybermax/google-trends) · [Gripeline](https://apify.com/cybermax/app-reviews) · [Keyfern](https://apify.com/cybermax/keyword-ideas) · [Linkheft](https://apify.com/cybermax/domain-authority) · [Printwren](https://huggingface.co/spaces/shaw276/docs-pages-as-pdfs?soon=html-to-pdf)

### How it works and what it collects

Every job comes from the unauthenticated JSON feed that the ATS vendor publishes for the employer's own careers page. The Actor collects no personal data and never logs in. The board directory was built from the Common Crawl URL index and each board was validated live; companies can always be searched directly with `companies`.

Built by CyberMax. Questions or a missing company? Open an issue on the Actor page.

### Changelog

- 2026-09-23: Monitor mode documented (`newOnly`/`stateKey`, aliases `monitor`/`monitorKey`; new jobs are marked `change: "new"`, `SUMMARY` adds `newJobs`/`alreadySeenJobs`), schedule & integration recipes, one-company prefill.

# Actor input Schema

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

Jobs whose title contains ANY of these words or phrases (whole words, case-insensitive), e.g. "data engineer", "account executive", "nurse". Leave empty to get every job that passes the other filters.

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

Jobs whose location contains ANY of these, e.g. "United States", "London", "Germany", "Remote". "United States"/"US"/"USA", "UK" and "New York"/"NYC" match their common spellings. Leave empty for anywhere.

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

Only jobs the employer marks as remote (or whose location says remote/anywhere).

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

Only jobs first posted in the last N days. Jobs without a posted date are left out when this is set.

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

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

## `maxJobs` (type: `integer`):

Newest jobs first. Each returned job is charged; the run summary tells you how many more matched.

## `newOnly` (type: `boolean`):

Monitor mode. Remembers which jobs this search already returned (in a key-value store named hireheat-jobs-state in your account) and returns only new postings, marked change: "new". Already-seen jobs are not returned or charged. Schedule the Actor daily for a job-alert feed. (Also accepted as "monitor": true.)

## `stateKey` (type: `string`):

Optional. Name for the remembered state, so several alert feeds with different filters stay separate. By default the filters themselves are the key. (Also accepted as "monitorKey".)

## `ats` (type: `array`):

Which career-site platforms to search. Default: Greenhouse, Ashby, Workable, SmartRecruiters (and Lever for companies you list). Recruitee (1,800 mostly European employers) is opt-in because it rate-limits cloud servers and makes searches slower.

## `companyNames` (type: `array`):

Optional. Search only directory companies whose name or board slug contains one of these, e.g. "stripe", "notion".

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

Optional. Instead of the built-in directory, search these companies: domains (acme.com) or job-board URLs (https://jobs.lever.co/acme). The Actor finds each company's board itself, including Lever.

## `maxBoards` (type: `integer`):

Optional. Search an evenly spread sample of this many directory boards instead of all 12,000+, for a quick, cheaper test.

## `maxRunSecs` (type: `integer`):

The search stops opening new boards after this long and returns everything found so far (biggest employers are read first). The run summary says how many boards were left unread.

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

Upper limit on how many boards of one platform are read at once (each platform has its own polite default, 4–32).

## `timeoutSecs` (type: `integer`):

Timeout for each career-site request.

## Actor input object example

```json
{
  "keywords": [
    "engineer"
  ],
  "remoteOnly": false,
  "excludeKeywords": [],
  "maxJobs": 3,
  "newOnly": false,
  "ats": [],
  "companyNames": [
    "vercel"
  ],
  "companies": [],
  "maxRunSecs": 300,
  "maxConcurrency": 32,
  "timeoutSecs": 10
}
```

# Actor output Schema

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

No description

## `summary` (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 = {
    "keywords": [
        "engineer"
    ],
    "maxJobs": 3,
    "companyNames": [
        "vercel"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("cybermax/career-site-jobs").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": ["engineer"],
    "maxJobs": 3,
    "companyNames": ["vercel"],
}

# Run the Actor and wait for it to finish
run = client.actor("cybermax/career-site-jobs").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": [
    "engineer"
  ],
  "maxJobs": 3,
  "companyNames": [
    "vercel"
  ]
}' |
apify call cybermax/career-site-jobs --silent --output-dataset

```

## MCP server setup

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

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/WM6r5mfaW348SEEJM/builds/lxQ6n5MEyWpzJ4C6Y/openapi.json
