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

Scrape job postings and public compensation from any Ashby job board (jobs.ashbyhq.com): title, team, locations, remote, employment type, salary range, equity/bonus flags, dates, apply URL and description. Filters included. From US$1.00 per 1,000 jobs.

- **URL**: https://apify.com/fabrikit/ashby-jobs-scraper.md
- **Developed by:** [Fabrikit](https://apify.com/fabrikit) (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 postings

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

## Ashby Jobs Scraper

Ashby is a fast-growing applicant tracking system used by startups and scale-ups, with career pages at `jobs.ashbyhq.com/<company>`. This Actor reads each company's public Ashby job board and returns uniform job records, including the compensation data Ashby publishes: salary range, currency, interval, equity and bonus flags and the per-tier summaries.

Price: **US$1.00 per 1,000 jobs**, no subscription. Platform usage is included in the per-job price.

### What you can do

- Board names or any `jobs.ashbyhq.com` URL; a single posting URL scrapes just that job.
- Compensation: `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryInterval`, a readable `compensationSummary`, `offersEquity`, `offersBonus` and the pay tiers.
- All locations (primary plus secondary), country, city and region, remote / hybrid / on-site.
- Filters: keywords, exclude keywords, locations, departments, teams, employment type, workplace type, remote only, posted within N days.
- Optional full description as plain text and HTML.
- Direct requests to a public API: no browser, no login, very cheap to run.

### Input

| Field | What it does |
|---|---|
| `companies` | Ashby companies: slug or URL (required) |
| `maxItems` | Total cap on jobs for the run (default 100) |
| `maxJobsPerCompany` | Optional per-company cap |
| `keywords` / `excludeKeywords` | Keep / drop jobs mentioning any of these words |
| `locations`, `departments`, `teams`, `employmentTypes` | Keep jobs containing any of these values |
| `workplaceTypes`, `remoteOnly` | Remote, hybrid or on-site |
| `postedWithinDays` | Only recent jobs |
| `includeDescription` | Add full description text and HTML |
| `proxyConfiguration` | Leave the default; used only if the source blocks |

Example:

```json
{
  "companies": [
    "ramp",
    "openai"
  ],
  "maxItems": 200,
  "departments": [
    "Engineering"
  ],
  "workplaceTypes": [
    "remote"
  ],
  "includeDescription": false
}
```

### Output

One dataset item per job. Salary fields are filled when the posting publishes compensation; `compensationSummary` keeps Ashby's own readable text (for example `EUR 110K - 185K, Offers Equity`).

| Field | Description |
|---|---|
| `platform`, `jobId` | Source platform and the posting's ID there |
| `title`, `company`, `companyName` | Job title; company slug as used in the URL; display name when the platform provides it |
| `location`, `locations`, `country` | Main location, all locations, country |
| `remote`, `workplaceType` | Remote flag and `remote` / `hybrid` / `onsite` when known |
| `department`, `team`, `employmentType` | Organisation and contract type |
| `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryInterval`, `compensationSummary` | Public compensation when the platform exposes it, otherwise `null` |
| `postedAt`, `updatedAt` | ISO timestamps when known |
| `jobUrl`, `applyUrl` | Public posting and application links |
| `descriptionText`, `descriptionHtml` | Full description, only with `Include full description` |
| `scrapedAt` | When the record was produced |

Platform-specific extras are added after these fields (see the dataset schema).

Example item:

```json
{
  "platform": "ashby",
  "jobId": "34413f8d-26bf-4bbc-8ade-eb309a0e2245",
  "title": "Security Engineer, Cloud",
  "company": "ramp",
  "companyName": null,
  "location": "New York, NY (HQ)",
  "locations": [
    "New York, NY (HQ)",
    "Remote (Canada)",
    "Remote (US)"
  ],
  "country": "USA",
  "remote": true,
  "workplaceType": "hybrid",
  "department": "Engineering",
  "team": "Backend",
  "employmentType": "Full-time",
  "salaryMin": 211400,
  "salaryMax": 290600,
  "salaryCurrency": "USD",
  "salaryInterval": "year",
  "compensationSummary": "$211.4K – $290.6K • Offers Equity",
  "postedAt": "2026-04-07T17:12:35.753Z",
  "updatedAt": null,
  "applyUrl": "https://jobs.ashbyhq.com/ramp/34413f8d-26bf-4bbc-8ade-eb309a0e2245/application",
  "jobUrl": "https://jobs.ashbyhq.com/ramp/34413f8d-26bf-4bbc-8ade-eb309a0e2245",
  "descriptionText": "ABOUT RAMP\n\nRamp is building the smart infrastructure for finance teams, embedded in the transaction flow of every dollar a business spends. We automate how ove...",
  "descriptionHtml": "<h1><strong>About Ramp</strong></h1><p style=\"min-height:1.5em\">Ramp is building the smart infrastructure for finance te...",
  "city": "New York City",
  "region": "NY",
  "offersEquity": true,
  "offersBonus": false,
  "compensationTiers": [
    {
      "title": null,
      "summary": "$211.4K – $290.6K • Offers Equity",
      "additionalInformation": null
    }
  ],
  "scrapedAt": "2026-10-13T15:09:17.262Z"
}
```

A `SUMMARY` record in the key-value store lists, per company, how many postings were found, how many matched your filters, and why the run stopped.

### Pricing

| Event | Price |
|---|---|
| Job posting saved to the dataset (`job-result`) | US$0.001 (US$1.00 per 1,000) |

You only pay for jobs that match your filters and are saved. Set a maximum cost per run in the Apify console and the Actor stops cleanly when it is reached.

### Use cases

- Salary benchmarking for startup roles.
- Recruiting and sourcing at venture-backed companies.
- Market intelligence: which teams are growing, where, and at what pay.
- Job alerts and aggregators.

### FAQ

**Is compensation always present?**
No. Ashby only exposes it when the employer chose to publish it on the posting. In a typical startup board a majority of postings carry a range (US and EU pay-transparency rules help), but some boards show none. Jobs without public compensation have the salary fields set to `null`.

**What is the board name?**
The first path segment of the career page, e.g. `ramp` in `https://jobs.ashbyhq.com/ramp`.

**Do I need an account, API key or proxy?**
No. The data comes from public career pages and feeds. Requests go out directly; if a source ever blocks them the Actor climbs automatically to Apify datacenter and then residential proxies.

**What personal data is included?**
Only company and job data. Recruiter, hiring-manager and contact names are not collected, and emails, phone numbers and personal profile links are removed from descriptions.

**How many jobs can I get?**
Everything the company has published right now, up to `Max jobs`. Large boards with thousands of postings are fine.

**What happens if a company is not found?**
It is skipped with a warning and listed in the `SUMMARY` record. If none of your companies exist, the run fails with a clear message instead of finishing with an empty dataset.

**Is it legal?**
The Actor reads publicly accessible job listings that employers publish for candidates and does not log in or bypass any protection. You remain responsible for how you use the data and for complying with the platform's terms and applicable law (for example data-protection rules if you combine it with personal data).

### En espanol

Extrae ofertas de cualquier tablero de Ashby (`jobs.ashbyhq.com`) con la compensacion que la empresa publica: rango salarial, moneda, intervalo, equity y bonus. Incluye ubicaciones, remoto/hibrido, filtros y descripcion completa opcional. Precio: US$1,00 por 1.000 ofertas.

# Actor input Schema

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

Ashby job board names (`ramp`) or URLs (`https://jobs.ashbyhq.com/ramp`). A job URL scrapes just that posting. The name is the first part of the path on jobs.ashbyhq.com.

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

Stop after this many jobs in total (all companies together).

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

Keep at most this many matching jobs per company. 0 = no limit.

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

Keep only jobs whose title, department, team, employment type or description contains ANY of these words (case and accent insensitive). Leave empty for all jobs.

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

Drop jobs that contain ANY of these words (same fields as Keywords).

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

Keep jobs whose location text contains ANY of these (e.g. `Berlin`, `Remote`, `United States`, `Santiago`).

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

Keep jobs whose department contains ANY of these (e.g. `Engineering`, `Sales`).

## `teams` (type: `array`):

Keep jobs whose team contains ANY of these.

## `employmentTypes` (type: `array`):

Keep jobs whose employment type contains ANY of these (e.g. `Full-time`, `Intern`, `Contract`, `Permanent`).

## `workplaceTypes` (type: `array`):

Keep only these workplace models.

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

Keep only jobs flagged as remote.

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

Keep only jobs published in the last N days. 0 = any age.

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

Add `descriptionText` and `descriptionHtml`. Makes the dataset larger. Emails, phone numbers and personal profile links are removed.

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

Requests go direct first (the source is a public API). If the source ever blocks them, the Actor climbs automatically to Apify datacenter and then residential proxies. Leave the default.

## Actor input object example

```json
{
  "companies": [
    "ramp"
  ],
  "maxItems": 50,
  "maxJobsPerCompany": 0,
  "remoteOnly": false,
  "postedWithinDays": 0,
  "includeDescription": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

All job postings collected during the run

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

Per-company counts, filters applied, proxy rung and stop reason

# 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": [
        "ramp"
    ],
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("fabrikit/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 = {
    "companies": ["ramp"],
    "maxItems": 50,
    "proxyConfiguration": { "useApifyProxy": True },
}

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,fabrikit/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/MmasIPaLGmGVbHPvX/builds/QMzeh0j7He7T26njH/openapi.json
