# Workable Jobs Scraper (`deriverge/workable-jobs-scraper`) Actor

Open jobs from any Workable job board with department, location, workplace type, employment type and posting date, plus the ad text on request. Enter account names, board links or company domains, or leave the list empty to search more than 70,000 open Workable jobs in our daily index.

- **URL**: https://apify.com/deriverge/workable-jobs-scraper.md
- **Developed by:** [deriverge s.r.o.](https://apify.com/deriverge) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 80.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 jobs

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Workable Jobs Scraper

Workable Jobs Scraper returns the open jobs on the Workable boards you list, one row per job: title, department, location, workplace type (on-site, hybrid or remote), employment type, posting date and the link, with the ad text on request. Enter account names such as `suade` or board links such as `https://apply.workable.com/suade/` in **Career sites** and click **Start**. With the list empty, it searches our daily index of more than 70,000 open Workable jobs. Workable boards show no pay field, so pay comes only from amounts written in the ad. It costs $1.00 per 1,000 jobs on the Free plan ($0.50 on Business), and the $5 of monthly credit in Apify's Free plan covers about 5,000 jobs.

### What data does it return?

| Field | Description |
|---|---|
| `title`, `department` | Job title and the first department on the board, such as `CS/Group` or `Engineering`. |
| `locations`, `countries` | City, region and country as Workable lists them, such as `High Wycombe, Buckinghamshire, United Kingdom`, and the country codes, here `GB`. |
| `workplaceType`, `workArrangement`, `remote` | Workable's `on_site`, `hybrid` or `remote`, the same as `onsite`, `hybrid` or `remote`, and `remote` as `true` for remote jobs, `false` for hybrid ones and `null` for on-site ones. |
| `employmentType`, `employmentTypes` | Workable's own value, such as `full` or `contract`, and the normalized types read from the field and the title. `full` is not translated, so the list is empty for most jobs read from boards. |
| `postedAt` | The day the job was published on Workable, as midnight UTC. Some boards keep jobs open for a long time: one in our runs dated from August 2024. |
| `companyName` | The account's display name, such as `The Focusrite Group`. |
| `url` | The job page, `https://apply.workable.com/<account>/j/<code>/`, where candidates also apply. |
| `description`, `language` | The ad as plain text, made of Workable's description, requirements and benefits sections, and its language code. The description needs **Include the full job description**. |
| `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod`, `salaryYearlyMin`, `salaryYearlyMax` | Pay found in the ad text, such as `65000` to `75000` GBP a year, and the same per year. Empty when the ad states none or descriptions are off. |
| `skills`, `experienceYearsMin`, `experienceYearsMax`, `educationLevel`, `visaSponsorship` | Read from the ad: tools and certificates such as `IFRS` or `NetSuite`, years of experience, the lowest degree mentioned and what the ad says about visa sponsorship. |
| `seniority`, `jobCategory` | Level and category read from the title, such as `mid` and `finance`. |
| `key`, `jobId`, `company`, `input`, `reference`, `firstSeenAt` | Stable key `workable:<account>:<code>`, Workable's job code, the account name, your input line, your own label and when this run read the job. |
| `salaryText`, `team`, `updatedAt`, `companyWebsite`, `applyUrl` | Always empty for boards you list: Workable does not publish these, and the application form sits on the page in `url`. |

### How to scrape Workable jobs

1. List the companies in **Career sites**, one per line: the account name (`suade`), the board link (`https://apply.workable.com/suade/`) or the company's domain (`suade.org`). The actor finds the account from Workable links on the company's careers page. Lines that lead to another applicant tracking system are skipped and named in `SUMMARY`.
2. Narrow the jobs with **Title keywords (any of)**, **Locations (any of)**, **Countries** or **Work arrangement**, which on Workable comes mostly from the board's own workplace field.
3. Turn on **Include the full job description** for the ad text and what is read from it: pay, skills, experience and education. It takes one extra request per job, so the run takes longer.
4. Click **Start**. The jobs show up in the **Output** tab for export as CSV, Excel or JSON, and the `SUMMARY` record counts the jobs on each board.

For API users, hybrid and remote jobs at three companies with their descriptions:

```json
{
  "companies": ["suade.org", "focusrite", "https://apply.workable.com/epignosis/"],
  "workArrangement": ["hybrid", "remote"],
  "includeDescription": true
}
```

### Example output

A job from a run on 11 October 2026 over five boards with descriptions on. Its `description` is cut after the lines about place, term and salary, marked ` ...`.

```json
{
  "key": "workable:focusrite:4AC7182C95",
  "ats": "workable",
  "company": "focusrite",
  "companyName": "The Focusrite Group",
  "jobId": "4AC7182C95",
  "title": "Financial Accountant",
  "locations": [
    "High Wycombe, Buckinghamshire, United Kingdom"
  ],
  "remote": false,
  "department": "CS/Group",
  "team": null,
  "employmentType": "full",
  "workplaceType": "hybrid",
  "salaryText": null,
  "postedAt": "2026-10-06T00:00:00.000Z",
  "updatedAt": null,
  "url": "https://apply.workable.com/focusrite/j/4AC7182C95/",
  "applyUrl": null,
  "description": "Financial Accountant\nBased: Hybrid with offices based in High Wycombe\nTerm: Permanent, Full time\nSalary: £65000-£75000 pa + excellent benefits ...",
  "language": "en",
  "reference": null,
  "input": "workable:focusrite",
  "firstSeenAt": "2026-10-11T16:45:05.189Z",
  "seniority": "mid",
  "jobCategory": "finance",
  "employmentTypes": [],
  "workArrangement": "hybrid",
  "countries": [
    "GB"
  ],
  "salaryMin": 65000,
  "salaryMax": 75000,
  "salaryCurrency": "GBP",
  "salaryPeriod": "year",
  "salaryYearlyMin": 65000,
  "salaryYearlyMax": 75000,
  "visaSponsorship": null,
  "skills": [
    "IFRS",
    "Excel",
    "NetSuite"
  ],
  "experienceYearsMin": null,
  "experienceYearsMax": null,
  "educationLevel": null
}
```

### How much does it cost to scrape Workable jobs?

| | Free plan | Starter | Scale | Business |
|---|---|---|---|---|
| 1,000 jobs | $1.00 | $0.80 | $0.65 | $0.50 |

You pay only for the events in the table. There is no start fee, and compute time and proxies are included.

Five boards (European Dynamics, Oxford Quantum Circuits, Focusrite, Epignosis and Suade) had 235 open jobs on 11 October 2026, which cost $0.235 on the Free plan and $0.1175 on Business. Filtered jobs, jobs already sent in new-only mode and inputs on other systems are not charged.

### Limits

- Workable limits how many requests one IP address may send. When it answers HTTP 429, the actor waits and tries twice more, then names the board as rate limited in `SUMMARY`; a run in which most boards were rate limited fails, and starting it again a few minutes later usually works.
- With descriptions on, up to 500 jobs per board get their ad, 5 at a time. The five boards above took 24 seconds, the two prefilled boards without ads 3 seconds.
- Pay appeared in the ads of 20 of the 235 jobs, all in British pounds. Workable's own salary field is not public.

### Searching all Workable jobs

Leave **Career sites** empty to search our nightly index of Workable jobs, which held more than 70,000 open jobs on 11 October 2026. Title keywords then match the title, results come newest first, and **Maximum jobs (index search)** ends the run at 1,000 unless you set it. Index rows put the company name in `company` and the account in `companySlug` and `careerSiteUrl`. Their `employmentType` uses Workable's wording such as `Full-time`, and their `workplaceType` marks remote jobs only.

A search for `engineer` or `developer` in the United Kingdom, Germany and Greece found 1,258 matches and returned the first 300 in 9 seconds. With **Include the full job description** on, each board in the result is read live during the run, so jobs closed since the night before drop out.

### FAQ

#### Is it legal to scrape Workable job boards?

Employers publish Workable boards so that anyone can read their openings and apply, and the actor reads the job data those public pages are built from, on paths their robots.txt allows. It collects nothing about candidates. How you use the jobs afterwards is your responsibility.

#### Where do I find a company's Workable account name?

It is the part after `apply.workable.com/` in the address of the company's job board, such as `suade` in `https://apply.workable.com/suade/`. If you only know the company's website, enter the domain and the actor looks for the board link on its careers page.

#### Can I get only new jobs every day?

Yes. Turn on **Return only jobs posted since the last run**, save the input as a task and schedule it. Each run then returns the jobs that were not on the boards at the previous run, and the `CHANGES` record counts the jobs that closed in between.

### Related scrapers

- [Career Site and ATS Jobs API](https://apify.com/deriverge/career-site-jobs-search)
- [Career Site Jobs Scraper](https://apify.com/deriverge/greenhouse-lever-workday-jobs-scraper)
- [Ashby Jobs Scraper](https://apify.com/deriverge/ashby-jobs-scraper)
- [BambooHR Jobs Scraper](https://apify.com/deriverge/bamboohr-jobs-scraper)
- [Lever Jobs Scraper](https://apify.com/deriverge/lever-jobs-scraper)

### Support

This actor is built and maintained by deriverge s.r.o., a software company based in the Czech Republic. If a run fails or a field you need is missing, please open an issue in the **Issues** tab or write to us at info@deriverge.com. We respond in English and Czech. Runs can be scheduled in Apify Console or started from the **API** tab, which has examples for Python, JavaScript and cURL and works with Make, Zapier, n8n and the Apify MCP server. If the actor saves you time, a short review helps other people find it.

# Changelog

This Actor's version history is a separate document: https://apify.com/deriverge/workable-jobs-scraper/changelog.md

# Actor input Schema

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

One entry per company: the Workable account name (action1), the Workable URL (https://apply.workable.com/action1/), or just the company domain (suade.org), which the actor resolves to the right board before it scrapes. Inputs pointing at another applicant tracking system are skipped and listed in the run summary. Leave this empty to search every open Workable job in our daily index instead, by keywords, country, seniority and the other filters below.

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

Keep only jobs whose title, department or team contains at least one of these words, case-insensitive. In the daily index search, when Career sites is left empty, only the title is matched. Leave empty to keep everything.

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

Drop jobs whose title, department or team contains any of these words. In the daily index search, when Career sites is left empty, the title and the company name are checked instead.

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

Keep only jobs whose location contains one of these strings, for example "London", "United States", "Remote".

## `countries` (type: `array`):

Keep only jobs in these countries: English names or two-letter codes, for example United States, Germany, UK or DE. Read from the job location, so "Austin, TX" counts as United States.

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

Keep only jobs the ATS marks as remote or whose location says remote.

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

Drop jobs older than this many days when the ATS provides a posting date. Leave empty for no limit.

## `seniority` (type: `array`):

Read from the job title in English, German, French, Spanish and more. Titles without a level count as mid.

## `categories` (type: `array`):

Read from the job title (and the department when the title says nothing), for example software, healthcare, sales or logistics. Jobs whose title fits no category are left out when this filter is on.

## `workArrangement` (type: `array`):

From the workplace field, the location and clear sentences in the description. Jobs with a place and no remote or hybrid mention count as on-site.

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

Only jobs whose employment field or title states one of these types.

## `hasSalary` (type: `boolean`):

Only jobs that state pay, from the salary field or a pay range in the description (turn on the description to catch more).

## `minYearlySalary` (type: `integer`):

Only jobs whose pay, converted to a year (hourly × 2,080, monthly × 12), reaches this amount in the currency below, for example 120000.

## `salaryCurrency` (type: `string`):

Currency of the minimum yearly salary: USD, EUR, GBP, CAD, AUD and so on.

## `visaSponsorship` (type: `boolean`):

Only jobs whose description says the company sponsors visas. Reads the description.

## `descriptionKeywords` (type: `array`):

Only jobs whose title or description contains any of these, for example "python" or "SAP". Reads the description.

## `excludeDescriptionKeywords` (type: `array`):

Drop jobs whose title or description contains any of these, for example "security clearance".

## `skills` (type: `array`):

Only jobs that ask for all of these skills, for example Python, AWS or Salesforce. Known tools, languages and certifications match their other spellings (golang, k8s, postgres); anything else is matched as a whole word in the title or description.

## `maxYearsOfExperience` (type: `integer`):

Leave out jobs whose description asks for more years of experience than this, for example 2 for junior roles. Jobs that do not state years are kept.

## `languages` (type: `array`):

Only jobs written in these languages, as two-letter codes or names, for example en or English to find English-language jobs in Germany. Detected from the description.

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

Adds the job description as plain text. Costs one extra request per job on SmartRecruiters, Workable, Workday and BambooHR, so runs take longer there.

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

Keeps a snapshot per watch name (or per saved task) and returns only jobs that were not in the previous snapshot. Schedule the task daily and you get a hiring-signal feed: every new opening, once, the day it appears. Closed jobs are counted in the CHANGES record.

## `watchName` (type: `string`):

Name of the snapshot used by the new-only mode, for example "competitors". Runs from a saved task get a snapshot automatically even without a name.

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

Caps the number of jobs returned per career site. Leave empty for all.

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

Cap on jobs returned when Career sites is empty and the daily index is searched, newest first; empty means 1,000.

## Actor input object example

```json
{
  "companies": [
    "action1",
    "costello-medical",
    "luminance-1"
  ],
  "remoteOnly": false,
  "hasSalary": false,
  "salaryCurrency": "USD",
  "visaSponsorship": false,
  "includeDescription": false,
  "newOnly": false,
  "maxJobsPerCompany": 10
}
```

# Actor output Schema

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

One row per job with the unified schema: title, locations, remote, department, employment type, salary text where the ATS provides it, posting date, links and optional description.

## `changes` (type: `string`):

New, closed and retitled jobs compared with the previous snapshot of the same watch name or task.

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

Per-company counts, skipped inputs with reasons, and totals.

# 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": [
        "action1",
        "costello-medical",
        "luminance-1"
    ],
    "maxJobsPerCompany": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("deriverge/workable-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": [
        "action1",
        "costello-medical",
        "luminance-1",
    ],
    "maxJobsPerCompany": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("deriverge/workable-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": [
    "action1",
    "costello-medical",
    "luminance-1"
  ],
  "maxJobsPerCompany": 10
}' |
apify call deriverge/workable-jobs-scraper --silent --output-dataset

```

## MCP server setup

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