# Direct-Source Jobs Scraper — Greenhouse · Lever · Ashby (`gunmo/direct-source-jobs-scraper`) Actor

Job postings straight from employer career boards (ATS). Zero job-board noise: no recruiter spam, no reposts, deduplicated, one clean schema.

- **URL**: https://apify.com/gunmo/direct-source-jobs-scraper.md
- **Developed by:** [Gunmo Goo](https://apify.com/gunmo) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 job returneds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Direct-Source Jobs Scraper — Greenhouse · Lever · Ashby

Get job postings **straight from employer career boards** — not from job boards.

### Why direct-source?

Job boards are noisy: recruiter spam, third-party reposts, expired listings, duplicates.
This Actor pulls from the source of truth — the company's own ATS board — and returns
**one clean, normalized schema** across Greenhouse, Lever, and Ashby:

- ✅ **Zero recruiter spam** — employer boards only
- ✅ **API-based, not HTML scraping** — reads the official public JSON endpoints each ATS exposes for careers pages. Career-site redesigns don't break it, and there are no proxies or browsers involved.
- ✅ **No reposts, no duplicates** — content-based dedup IDs (same role reposted = same ID), duplicates removed within each run. Postings with identical company + title + location collapse into one item; the original ATS requisition ID is always preserved in `source.source_id`.
- ✅ **One schema for 3 ATS platforms** — stop writing per-ATS parsers
- ✅ **ATS auto-detection** — just give it a token like `stripe`; it figures out the rest
- ✅ **Remote detection** — explicit ATS flags + location heuristics
- ✅ **New-jobs-only mode** (`onlyNewSinceLastRun`) — schedule it and get only never-seen-before postings; you're only charged for new jobs
- ✅ **Filters** — title keywords, departments, posted-after date, remote-only; filtered-out jobs are never charged
- ✅ **Honest billing, engineered in** — you pay only for jobs that land in your dataset. Interrupted or migrated runs resume from a checkpoint and **never push or charge the same job twice**, and your *Maximum cost per run* is respected instead of overshot. ([details](#pricing--honest-billing))
- ✅ **Built-in registry of 200+ verified companies** — set `useRegistry: true` and scrape a maintained list without building your own

### Input

```json
{
  "companies": ["stripe", "openai", "gitlab"],
  "remoteOnly": true,
  "titleKeywords": ["engineer", "developer"],
  "departments": ["engineering"],
  "postedAfter": "2026-06-01",
  "maxJobsPerCompany": 100
}
````

Or set `"useRegistry": true` to scrape a built-in, verified registry of **200+ tech companies** (each one probed and confirmed against its live ATS board).

`titleKeywords` and `departments` match case-insensitively (any keyword matches). `postedAfter`
keeps only jobs published on or after that date — jobs whose ATS doesn't report a publish date
are excluded when this filter is set.

### Output (Dataset)

```json
{
  "id": "e7d7dcd2c73dc668",
  "company": "GitLab",
  "title": "AI Engineer",
  "location": { "raw": "Remote, US", "city": null, "country": null },
  "remote": true,
  "department": "Enterprise Applications",
  "employment_type": "Full-time",
  "salary": null,
  "posted_at": "2026-04-17T12:07:26.000Z",
  "description_html": "<p>...</p>",
  "apply_url": "https://job-boards.greenhouse.io/gitlab/jobs/8565469002",
  "source": { "ats": "greenhouse", "source_id": "8565469002", "fetched_at": "2026-07-02T15:01:00.000Z" }
}
```

### Use cases

- **Recruiting tools & job boards** — clean inventory without scraping 3 ATS APIs yourself
- **Sales intelligence / lead-gen** — hiring signals as buying intent (who's hiring for what)
- **Market research** — track hiring trends across companies and departments
- **Job alert products** — set `onlyNewSinceLastRun: true` on a schedule and receive only new postings

### Reliability

- **JSON endpoints only** — no HTML parsing, so career-page redesigns don't affect results (as long as the ATS keeps its public API, which powers the vendor's own embed widgets).
- **Per-company failure isolation** — one broken board never fails the whole run; failures are listed in the run's `SUMMARY` key-value record.
- **Honest failure signal** — if *every* target fails, the run exits as **failed** instead of "succeeded with 0 items", so your schedules and monitoring actually notice.
- **Malformed postings are skipped, not fatal** — a single bad record can't crash a board's collection; skip counts are reported in `SUMMARY`.

### Pricing & honest billing

Pay-per-event: you're charged per job returned. No subscription, no minimum.

- **You only pay for what lands in your dataset.** Jobs removed by dedup, filters, or new-jobs-only mode are never charged.
- **No double billing on interruptions.** If a run is migrated or restarted, it resumes from a checkpoint: companies already scraped are skipped and already-delivered jobs are never pushed or charged twice.
- **Cost cap respected.** If you set *Maximum cost per run*, collection stops at the limit instead of overshooting it.

### Fair use & compliance

This Actor only accesses **public, unauthenticated** job board endpoints that ATS vendors
expose for embedding careers pages. It respects rate limits (sequential, delayed requests),
identifies itself with a contact User-Agent, and collects **no personal or applicant data** —
only public job postings.

# Actor input Schema

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

ATS board tokens, e.g. <code>stripe</code>, <code>openai</code>, <code>gitlab</code>. The ATS (Greenhouse / Lever / Ashby) is detected automatically for each token.

## `useRegistry` (type: `boolean`):

Scrape the built-in, verified registry of tech companies (in addition to any tokens above).

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

Return only jobs marked or detected as remote.

## `titleKeywords` (type: `array`):

Return only jobs whose title contains at least one of these keywords (case-insensitive), e.g. <code>engineer</code>, <code>designer</code>. Leave empty to return all titles.

## `departments` (type: `array`):

Return only jobs whose department contains at least one of these terms (case-insensitive), e.g. <code>engineering</code>, <code>sales</code>. Jobs without a department are excluded when this filter is set.

## `postedAfter` (type: `string`):

Return only jobs published on or after this date (ISO 8601, e.g. <code>2026-06-01</code>). Jobs whose ATS does not report a publish date are excluded when this filter is set.

## `maxJobsPerCompany` (type: `integer`):

Optional cap on the number of jobs returned per company.

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

Return only jobs never seen in previous runs — ideal for job alerts and hiring-signal feeds on a schedule. The first run returns everything as a baseline. You are only charged for new jobs.

## Actor input object example

```json
{
  "companies": [
    "stripe",
    "openai",
    "gitlab"
  ],
  "useRegistry": false,
  "remoteOnly": false,
  "titleKeywords": [],
  "departments": [],
  "onlyNewSinceLastRun": false
}
```

# 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 = {
    "companies": [
        "stripe",
        "openai",
        "gitlab"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("gunmo/direct-source-jobs-scraper").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 = { "companies": [
        "stripe",
        "openai",
        "gitlab",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("gunmo/direct-source-jobs-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "companies": [
    "stripe",
    "openai",
    "gitlab"
  ]
}' |
apify call gunmo/direct-source-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=gunmo/direct-source-jobs-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Direct-Source Jobs Scraper — Greenhouse · Lever · Ashby",
        "description": "Job postings straight from employer career boards (ATS). Zero job-board noise: no recruiter spam, no reposts, deduplicated, one clean schema.",
        "version": "0.1",
        "x-build-id": "DmhZq7zPKc2ACaf42"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/gunmo~direct-source-jobs-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-gunmo-direct-source-jobs-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/gunmo~direct-source-jobs-scraper/runs": {
            "post": {
                "operationId": "runs-sync-gunmo-direct-source-jobs-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/gunmo~direct-source-jobs-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-gunmo-direct-source-jobs-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": {
                    "companies": {
                        "title": "Company board tokens",
                        "type": "array",
                        "description": "ATS board tokens, e.g. <code>stripe</code>, <code>openai</code>, <code>gitlab</code>. The ATS (Greenhouse / Lever / Ashby) is detected automatically for each token.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "useRegistry": {
                        "title": "Use built-in company registry",
                        "type": "boolean",
                        "description": "Scrape the built-in, verified registry of tech companies (in addition to any tokens above).",
                        "default": false
                    },
                    "remoteOnly": {
                        "title": "Remote jobs only",
                        "type": "boolean",
                        "description": "Return only jobs marked or detected as remote.",
                        "default": false
                    },
                    "titleKeywords": {
                        "title": "Title keywords",
                        "type": "array",
                        "description": "Return only jobs whose title contains at least one of these keywords (case-insensitive), e.g. <code>engineer</code>, <code>designer</code>. Leave empty to return all titles.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "departments": {
                        "title": "Departments",
                        "type": "array",
                        "description": "Return only jobs whose department contains at least one of these terms (case-insensitive), e.g. <code>engineering</code>, <code>sales</code>. Jobs without a department are excluded when this filter is set.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "postedAfter": {
                        "title": "Posted after",
                        "type": "string",
                        "description": "Return only jobs published on or after this date (ISO 8601, e.g. <code>2026-06-01</code>). Jobs whose ATS does not report a publish date are excluded when this filter is set."
                    },
                    "maxJobsPerCompany": {
                        "title": "Max jobs per company",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Optional cap on the number of jobs returned per company."
                    },
                    "onlyNewSinceLastRun": {
                        "title": "Only new jobs since last run",
                        "type": "boolean",
                        "description": "Return only jobs never seen in previous runs — ideal for job alerts and hiring-signal feeds on a schedule. The first run returns everything as a baseline. You are only charged for new jobs.",
                        "default": false
                    }
                }
            },
            "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
                                    }
                                }
                            },
                            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
