# Ashby Jobs Scraper (`devilscrapes/ashby-jobs-scraper`) Actor

Scrape every job posting from any Ashby-hosted job board via Ashby's own public keyless GraphQL API, no login or browser required. Get team names, workplace type, employment type, compensation bands, and a guaranteed working apply link for every posting, in one full-board call per org.

- **URL**: https://apify.com/devilscrapes/ashby-jobs-scraper.md
- **Developed by:** [DevilScrapes](https://apify.com/devilscrapes) (community)
- **Categories:** Jobs
- **Stats:** 2 total users, 1 monthly users, 100.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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

<div align="center">
  <img src="https://apify.com/.actor/icon.svg" width="160" alt="Devil Scrapes mark" />

## Ashby Jobs Scraper

**💰 $1.70 / 1 000 results**  ·  pay only for results  ·  no credit card to try

*We do the dirty work so your dataset stays clean.* 😈

Scrape every job posting from any Ashby-hosted job board via Ashby's own public keyless GraphQL API — no login, no browser, no API key. Give it a list of org slugs and get titles, teams, locations, workplace type, compensation bands, and guaranteed working apply links as clean typed rows.

</div>

***

### 🎯 What this scrapes

Ashby powers the careers page for a large slice of venture-backed startups and scale-ups. Every one of those boards is served by the same internal GraphQL endpoint (`jobs.ashbyhq.com/api/non-user-graphql?op=ApiJobBoardWithTeams`). This Actor talks to it directly: hand it one or more org slugs — the `{orgSlug}` in a `jobs.ashbyhq.com/{orgSlug}` board URL, e.g. `openai` — and it fetches the entire board in a single call, joins the response's own team hierarchy, and normalizes everything into one row schema. One scraper, every Ashby-hosted employer.

### 🔥 Features

- 🔑 **Keyless public GraphQL API** — no OAuth, no token, no per-org setup; the same endpoint the careers page itself calls.
- 📦 **Whole board in one call** — no pagination to chase; a 750-posting board comes back in a single response.
- 🏢 **Multi-org in one run** — pass many org slugs; rows come back identically shaped, tagged with `org_slug`.
- 🧩 **Real team names, not guesses** — `team_name` is joined from the response's own `teams` hierarchy, never a fabricated department field.
- 🔗 **Guaranteed apply link** — `apply_url` is constructed and confirmed live-resolvable for every posting, no extra HTTP call.
- 🔁 **We retry with backoff + rotate browser fingerprints** — `curl-cffi` presents a real browser handshake and retries transient `429/5xx` so a large multi-org batch finishes instead of dying midway.
- 🧊 **Clean, typed rows** — Pydantic-validated, ISO-8601 timestamps, stable IDs. Export JSON / CSV / Excel straight from the Apify Console.

### 💡 Use cases

- **Recruiting & sourcing** — track what a target company is hiring for, where, and on which team.
- **Job-board aggregation** — add dedicated Ashby coverage next to Workday / Greenhouse / Lever / SmartRecruiters in one pipeline.
- **Hiring-intent signal for SDR/GTM teams** — open reqs are a leading indicator of budget and headcount growth.
- **HR-tech data pipelines** — wire structured job rows into your CRM, dashboard, or n8n / Make workflow on a schedule.

### ⚙️ How to use it

1. Click **Try for free** at the top of the Store listing.
2. Add one or more **Org slugs** — the `{orgSlug}` from a `jobs.ashbyhq.com/{orgSlug}` careers URL (e.g. `openai`), or paste the full board URL.
3. Optionally set **Max results per org** and a **Location filter**.
4. Click **Start**. Rows stream into the dataset as each org's board is fetched.
5. Export from **Storage → Dataset** as JSON, CSV, or Excel — or pull via the Apify API.

### 📥 Input

| Field | Type | Required | Default | Notes |
|---|---|:--:|---|---|
| `orgSlugs` | `array` | ✅ | — | Ashby org slugs (the `{orgSlug}` in `jobs.ashbyhq.com/{orgSlug}`, e.g. `openai`), or full board URLs. |
| `maxResultsPerOrg` | `integer` | no | `500` | Cap on rows emitted per org, applied after the single full-board fetch. |
| `locationFilter` | `string` | no | `null` | Case-insensitive substring match against a posting's location(s). Client-side only. |
| `proxyConfiguration` | `object` | no | `{"useApifyProxy": true}` | Apify Proxy configuration. |

#### Example input

```json
{
  "orgSlugs": ["openai", "ramp"],
  "maxResultsPerOrg": 100,
  "locationFilter": null,
  "proxyConfiguration": { "useApifyProxy": true }
}
```

### 📤 Output

One row per job posting.

| Field | Type | Notes |
|---|---|---|
| `posting_id` | `string` | Stable Ashby posting id. |
| `title` | `string` | Job title. |
| `org_slug` | `string` | The org slug this posting belongs to. |
| `team_name` | `string \| null` | Joined from the board's own team hierarchy; `null` if unassigned. |
| `location_name` | `string` | Primary location. |
| `workplace_type` | `string \| null` | `Hybrid`, `OnSite`, or `Remote`. |
| `employment_type` | `string \| null` | e.g. `FullTime`. |
| `secondary_locations` | `array` | Additional locations, if any. |
| `compensation_summary` | `string \| null` | Compensation band, when the org publishes one. |
| `apply_url` | `string` | Guaranteed live apply link. |
| `scraped_at` | `string` | ISO-8601 timestamp. |

#### Example output

```json
{
  "posting_id": "7af121a1-d29a-4745-84c1-ef1b58a3b840",
  "title": "3P Silicon Architect",
  "org_slug": "openai",
  "team_name": null,
  "location_name": "San Francisco",
  "workplace_type": "Hybrid",
  "employment_type": "FullTime",
  "secondary_locations": ["Seattle"],
  "compensation_summary": "$342K – $555K • Offers Equity",
  "apply_url": "https://jobs.ashbyhq.com/openai/7af121a1-d29a-4745-84c1-ef1b58a3b840",
  "scraped_at": "2026-07-26T15:00:00Z"
}
```

### 💰 Pricing

Pay-per-event — you pay only for what lands in your dataset.

| Event | Price |
|---|---|
| Actor start | $0.20 (once per run) |
| Result | $0.0015 per job posting (**$1.70 / 1,000** including the start fee) |

### 🚧 Limitations

- Ashby coverage only — for Greenhouse, Lever, Workday, or SmartRecruiters, see the sibling Actors in the DevilScrapes fleet.
- This Actor's GraphQL endpoint (`jobs.ashbyhq.com/api/non-user-graphql`) is distinct from the Ashby path inside `multi-ats-jobs-scraper` — different host, different fields — so the two are not redundant with each other.
- No first-class `department` field — Ashby's schema doesn't expose one directly; `team_name` (the board's own team hierarchy) is the closest real grouping signal.
- No org-name enrichment — `org_slug` is the literal input slug, not an org display name (the endpoint doesn't expose one).
- No historical or removed postings — this Actor reflects the board's current, live state only.

### ❓ FAQ

**Does this need an Ashby account or API key?**
No — it calls Ashby's own public, keyless board endpoint, the same one the careers page uses.

**Can I pass a full board URL instead of a bare slug?**
Yes — either works. A full `jobs.ashbyhq.com/{orgSlug}` URL has its slug extracted automatically.

**What happens if an org isn't on Ashby, or isn't currently hiring?**
The run continues and reports zero rows for that org — never a silent failure and never a crash.

### 💬 Your feedback

Found a field that's missing, or a board that doesn't behave as documented? Open an issue on the Actor's Store page or reach out via [apify.com/DevilScrapes](https://apify.com/DevilScrapes) — we ship fixes fast.

# Actor input Schema

## `orgSlugs` (type: `array`):

Ashby org slug, e.g. "openai" (the path segment in jobs.ashbyhq.com/{orgSlug}), or a full board URL — the orgSlug is regex-extracted automatically. A plain string with no "jobs.ashbyhq.com" substring is used literally, unchanged (including case).

## `maxResultsPerOrg` (type: `integer`):

Cap job postings emitted per orgSlugs entry, applied client-side after the single full-board fetch — this endpoint has no server-side pagination.

## `locationFilter` (type: `string`):

Optional case-insensitive substring match against a posting's location or any of its secondary locations. Client-side only, adds zero extra HTTP calls. Leave empty to skip.

## `proxyConfiguration` (type: `object`):

Apify Proxy configuration. No anti-bot behaviour has been observed on Ashby's keyless GraphQL endpoint, so the standard (non-residential) group is enough.

## Actor input object example

```json
{
  "orgSlugs": [
    "openai"
  ],
  "maxResultsPerOrg": 500,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `datasetItems` (type: `string`):

All dataset items as JSON.

## `datasetItemsCsv` (type: `string`):

Same data exported to CSV.

## `datasetView` (type: `string`):

Open the run dataset in the Console.

# 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 = {
    "orgSlugs": [
        "openai"
    ],
    "maxResultsPerOrg": 500,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("devilscrapes/ashby-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 = {
    "orgSlugs": ["openai"],
    "maxResultsPerOrg": 500,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("devilscrapes/ashby-jobs-scraper").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 '{
  "orgSlugs": [
    "openai"
  ],
  "maxResultsPerOrg": 500,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call devilscrapes/ashby-jobs-scraper --silent --output-dataset

```

## MCP server setup

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

```

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/1X3H4p9pBzJVsrw0e/builds/zwXgPtG4PBPyKOhYN/openapi.json
