# Workable Jobs Scraper — API, no HTML (`wickfeed/workable-jobs-scraper`) Actor

Track new Workable job postings from 380 verified boards built in — or just type a company name. Clean spreadsheet, no login. $1 per 1,000 jobs.

- **URL**: https://apify.com/wickfeed/workable-jobs-scraper.md
- **Developed by:** [WickFeed](https://apify.com/wickfeed) (community)
- **Categories:** Jobs, Lead generation, MCP servers
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 1,000 job fetcheds

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/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

## Workable Jobs Scraper — API, no HTML

*Unofficial — not affiliated with or endorsed by Workable.*

*Data note: job descriptions are employer-published public data and may contain recruiter contact info; don't use it for spam.*

**Version 0.2.6 · live since 2026-07-15 · 380 Workable boards verified 2026-07-15 · $1 per 1,000 jobs, $0 to start.**

**Live status:** https://api.apify.com/v2/key-value-stores/WickFeed~wickfeed-public-status/records/status.json — real self-test results for every wickfeed scraper (pass/fail plus 30-day success rate), updated hourly, no login needed. Opens as raw data (JSON).

**Which WickFeed tool do you want?**
- Mixed systems, or unsure which one a company uses → [ATS Job Aggregator](https://apify.com/wickfeed/ats-job-aggregator)
- Greenhouse only → [Greenhouse Jobs Scraper](https://apify.com/wickfeed/greenhouse-jobs-scraper)
- Ashby only, with published salary ranges → [Ashby Jobs Scraper](https://apify.com/wickfeed/ashby-jobs-scraper)
- Workable only → **Workable Jobs Scraper (this page)**
- Companies and their live job counts, not job rows → [ATS Company Discovery](https://apify.com/wickfeed/ats-company-discovery)

Download every open job at the Workable companies you choose — a fresh snapshot each run, as a table you can export to CSV, Excel, or JSON. Pick the bundled list or paste a careers URL, then press Start. No token hunting, no HTML scraping, and no Workable login or API key is required — you just need an Apify account to run the tool.

**From click to CSV, four steps:**
1. Click **Try for free** and sign in to Apify.
2. Leave the demo boards as they are and click **Start**.
3. When the run finishes, open **Dataset** to see the rows.
4. Click **Export** to download CSV, Excel, or JSON.

**Built to keep running.** It reads Workable's public widget API — the exact JSON the careers page itself loads — and writes one row per job. Because it reads that JSON and never parses rendered HTML, a careers-page restyle doesn't touch it: HTML scrapers break every time a careers page gets restyled, and choke when the jobs are drawn in JavaScript — this reads the data feed directly instead. The one thing that can require an update is Workable changing that feed's shape (see Limitations). If a board goes bad mid-run it's isolated and reported, the rest of the run finishes, and you're not charged for the one that failed. On a schedule, each run hands back a fresh full snapshot of what's open that day.

> **Demo cost: a few cents.** The form comes prefilled with 3 demo boards (`capgemini-insurance`, `avomind`, `crossbordertalents`). Press **Start** and that first run tops out around **$0.15** — and Apify's **$5 monthly free credit** covers it, so your first runs cost nothing. You're charged only for jobs you actually get; empty, dead, or misspelled boards never cost a thing.

Every run returns a **fresh, full snapshot** of what's open today — not a day-over-day diff. To get only the *new and changed* jobs picked out for you, see the [ATS Job Aggregator](https://apify.com/wickfeed/ats-job-aggregator), the diff monitor for the whole family.

### What you get

A run over a few boards returns rows like these (real postings, fetched 2026-07-15):

| Company | Title | Location | Remote | Posted |
|---|---|---|---|---|
| Capgemini | Agile Dev Team Member III : .Net Core Full Stack Developer | Pune, Maharashtra, India | no | 2026-03-05 |
| Cross Border Talents | Account Executive (Native English + Dutch) | Madrid, Community of Madrid, Spain | no | 2026-06-25 |
| Avomind | (Senior) Consultant Data Strategy | Munich, Bavaria, Germany | no | 2026-06-19 |
| CXG | Automobil-Luxusmarken-Evaluator - Amberg | Weiden in der Oberpfalz, Bavaria, Germany | no | 2026-07-12 |

Each row also carries a stable `id`, `department`, the public application `url`, the plain-text description, and a fetch timestamp.

### Paste a link, type a name — no token hunting

You don't need to know a company's Workable "board token." In the **Companies** box, put whatever you already have — one company per line:

- **A careers page address.** Copy it straight from the browser: `https://apply.workable.com/capgemini-insurance`. This is the reliable path — the board id is right there in the address, so it always works.
- **A company name.** Type `CXG`. Typed names are matched against the bundled list of **380 verified Workable companies** — a starter directory, not every Workable company. If yours isn't in it, paste the careers page address instead.
- **A bare board token.** `capgemini-insurance`, exactly as before. Existing setups and saved runs keep working unchanged.

```json
{ "sources": ["CXG", "https://apply.workable.com/avomind", "crossbordertalents"] }
````

If an entry can't be read — a blank line, an address for a *different* hiring system (a Greenhouse or Ashby link pasted here is caught and named), or a company name that isn't in the bundled list — that one line is skipped with a plain-English note telling you exactly what to paste instead. It never silently runs empty, and the rest of your list still runs. Reliable in, reliable out.

### Quick start

1. **Add companies.** Just press **Start** to use the three demo boards already filled in (`capgemini-insurance`, `avomind`, `crossbordertalents`). Or paste careers-page addresses, type company names, or switch *Company list* to "All verified" to pull all 380 Workable boards.
2. **(Optional) Narrow it.** Add keywords (e.g. `engineer`, `sales`) or locations (e.g. `berlin`, `remote`) to keep only matching jobs.
3. **Press Start.** By default each board delivers up to 50 jobs — the first 50 that match your filters (or just the first 50 it finds, if you set none) — so the first run is quick and cheap. Bump *Max results per board* up once the output looks right.

> **Calling the API?** Send an empty input `{}` and you get the same three demo boards the form starts with — capped at 50 jobs each, about **$0.15**. So a first API call does exactly what pressing Start does: no empty run, no surprise bill.

### Bundled company list

Choose "All verified" and press Start — no token hunting. The list holds **380 Workable boards**, every one confirmed live against Workable's own API on **2026-07-15**. You can also add your own companies by hand in *Companies* (paste an `apply.workable.com/...` address, type a name, or enter a bare subdomain); the two lists merge and duplicates are removed.

### Output schema

One row per job, the same fields every time:

| Field | Meaning |
|---|---|
| `id` | Stable id `workable:<token>:<jobId>` — deduplicate on this. |
| `ats` | Always `workable` — the hiring system this row came from (kept so the schema matches the multi-ATS aggregator). |
| `companyToken` | The Workable subdomain this row came from (e.g. `huggingface`). |
| `company` | Account display name (Workable exposes it). |
| `title` | Job title. |
| `department` | Department when provided, else null. |
| `location` | City, state and country assembled into one string. |
| `remote` | true/false from Workable's telecommuting flag; null when unknown. |
| `url` | Public application URL. |
| `postedAt` | Publish date (ISO-8601), or null. |
| `updatedAt` | ISO-8601 string or null — always null for Workable (the widget API exposes no update time). |
| `salaryRaw` | Always null — the widget API doesn't expose pay (see FAQ). |
| `descriptionText` | Plain text, HTML stripped, capped at ~20,000 chars. |
| `fetchedAt` | When this run fetched the row. |
| `schemaVersion` | The output-record schema version (a number, currently `1`). See **Output contract** below. |

`updatedAt` is null because Workable's widget carries no update time. Turn on *Include raw HTML description* to also get `descriptionHtml`.

Two real records from a run over the `huggingface` board (fetched 2026-07-15) — every field present on every row, honest `null`s where Workable's widget doesn't expose a value:

```json
[
  {
    "id": "workable:huggingface:97904BAC90",
    "ats": "workable",
    "companyToken": "huggingface",
    "company": "Hugging Face",
    "title": "Data/Infrastructure Advocate Engineer - EMEA Remote",
    "department": "Product",
    "location": "Paris, Île-de-France, France",
    "remote": true,
    "url": "https://apply.workable.com/j/97904BAC90",
    "postedAt": "2026-05-29T00:00:00.000Z",
    "updatedAt": null,
    "salaryRaw": null,
    "descriptionText": "At Hugging Face we're on a journey to democratize good AI. As our first Data/Infrastructure Advocate Engineer, you'll bridge cutting-edge data infrastructure and the global community of data engineers …",
    "fetchedAt": "2026-07-15T18:00:00.000Z",
    "schemaVersion": 1
  },
  {
    "id": "workable:huggingface:CEACA06A2D",
    "ats": "workable",
    "companyToken": "huggingface",
    "company": "Hugging Face",
    "title": "Data/Infrastructure Advocate Engineer - US Remote",
    "department": "Product",
    "location": "New York, New York, United States",
    "remote": true,
    "url": "https://apply.workable.com/j/CEACA06A2D",
    "postedAt": "2026-05-29T00:00:00.000Z",
    "updatedAt": null,
    "salaryRaw": null,
    "descriptionText": "At Hugging Face we're on a journey to democratize good AI. As our first Data/Infrastructure Advocate Engineer, you'll bridge cutting-edge data infrastructure and the global community of data engineers …",
    "fetchedAt": "2026-07-15T18:00:00.000Z",
    "schemaVersion": 1
  }
]
```

#### Output contract (schema stability)

A shipped update shouldn't break your spreadsheet or your pipeline. Here's that promise, in writing:

- **A field never gets renamed or removed inside a major version.** The columns above — `id`, `title`, `url`, `descriptionText`, and the rest — keep their names and their meaning, so you can build on them safely.
- **A `null` is honest, not missing.** Where Workable's widget doesn't expose a value (`salaryRaw`, `updatedAt`, sometimes `department`), the field is still there, set to `null` — never dropped, so a column you read is always present.
- **New fields get added, never forced on you.** We may *add* a field over time; doing that never touches the fields you already read, so your existing code keeps working untouched.
- **A breaking change is loud, not silent.** If a field ever had to be renamed or removed, that's a major version bump — called out in the **Changelog** (and the Issues tab) before it lands, never a surprise on your next scheduled run.
- **`schemaVersion` is a breaking-contract version.** Every row carries it (it's in `RUN_SUMMARY` too). It's not the release number and not an exact-shape fingerprint: **adding a new field doesn't bump it** — it changes only when an existing field is renamed, removed, or retyped (a breaking change, which also bumps the major version). So while this number holds, every field you already read keeps its name, type, and meaning; new fields may have been added alongside. It's `1` today.
- **The field list is published for machines too.** The actor ships a machine-readable output schema (a JSON Schema of every field above), so a pipeline or AI agent can discover the exact row shape without parsing this table.

`updatedAt` and `salaryRaw` are always `null` for Workable (the widget exposes neither); `descriptionHtml` is added only when *Include raw HTML description* is on.

### Pricing

You pay for jobs delivered, nothing else: **$1.00 per 1,000 jobs**, and **$0 just to start a run** (that's the `job-fetched` event). An empty run, a dead board, a misspelled one — none of them cost anything.

**In plain numbers:** a job costs a tenth of a cent — $1 per 1,000 works out to **$0.001** each. So **500 jobs is about $0.50** and **2,000 jobs is about $2.00**. Dead boards, misspelled ones, and boards with no open roles come back empty and cost nothing — you pay for jobs you actually get.

**Free to try.** Apify's free plan includes monthly usage credit — enough to cover a first demo run at no cost, so you see the output before paying anything.

**How that compares.** Other single-system Workable job actors on the store list around **$1.15–$4 per 1,000** (feeds that cover several systems cost more), and most tack on a fee each time a run starts. This one is a flat **$1 per 1,000, no start fee**. A few listings do price lower per job and charge a fixed start fee instead — for example `automation-lab/workable-jobs-scraper` (about **$0.14–$0.58 per 1,000** plus a **$0.005 start fee**) and `fetch_cat/workable-jobs-scraper` (lower still per job, plus a **$0.005 start fee**), both checked 2026-07-16 — so on a large pull they can come in under this one, while on a very small run the fixed fee can tip it the other way. Prices move, so compare on the current listings. Store prices as listed 2026-07-15; competitor prices checked 2026-07-16.

**If a charge ever looks wrong,** open an issue on the **Issues tab** with your run ID. We look into it the same day, and if we over-billed you we file a credit request with Apify to put the money back on your account. (Apify pays this kind of seller compensation as account credit, not cash, so that's what we can promise and what we'll do — we can't speak for how Apify itself handles it.)

### Limitations (read this)

- **Public boards only.** It reads what a company publishes on its Workable board — not private ATS data, internal reqs, or candidate information.
- **No salary.** Workable's public widget API doesn't return pay, so every `salaryRaw` is null. If you need salary ranges, see the Ashby scraper below.
- **You supply the companies.** No API lists every Workable company, and this actor doesn't crawl. Use the bundled 380-board list, or read a token off a careers URL.
- **No server-side search.** Each board returns its whole job list; the keyword, location, remote and date filters run over the whole board after fetching, and *Max results per board* then caps the matching jobs delivered (so a match is never hidden past the cap).
- **Politeness.** Requests are capped at ~2/second with retries and backoff, so very large runs take proportionally longer.
- **Endpoint drift.** If Workable changes its response shape, the reader may need an update; a bad board is isolated and reported, never fatal.

### FAQ

#### I got few or zero jobs back — is it broken?

Usually not. Start with the simple checks: clear your **Keywords** and **Locations**, turn off **Remote only**, and raise **Max results per board** — narrow filters or a low cap are the common reasons a run looks thin. Then open the run's **Status** and **Logs** to spot a mistyped company or a board that came back empty. Still looks wrong? Open the **Issues tab** with your run link and we'll take a look.

*Advanced diagnostics: the per-board breakdown (fetched, matched, delivered, filtered, and any board errors) is saved to the run's key-value store as `RUN_SUMMARY`, and rows that fail validation go to `REJECTS` — check `RUN_SUMMARY` for a typo'd token. When a board has more matching jobs than the cap, its row shows how many matched, so you can raise *Max results per board* to get the rest.*

#### Does it scrape HTML?

No. It calls Workable's official public widget API and reads JSON — the very request your browser fires when a careers page loads. No proxies, no headless browser, nothing to knock over.

#### Is this allowed?

It reads the same public JSON feed your browser pulls when you open a Workable careers page — no login, no password, no API key, no HTML scraping. It only touches data a company chose to make public. What you do with the results is up to you, and you're responsible for that use — for example, don't use it for spam or unsolicited outreach. This describes how the tool works; it isn't legal advice.

#### Can I schedule daily runs?

Yes — use Apify's scheduler. Every run starts fresh and returns a full snapshot of every open role that day, so a daily schedule gives you today's complete list, not a running diff. This tool doesn't compare one day to the next. If you want only the *new and changed* jobs picked out (real alerts that bill only for what changed), the [Jobs Scraper API](https://apify.com/wickfeed/ats-job-aggregator) is the diff monitor and does exactly that.

#### What happens to a dead or misspelled board?

It's skipped and noted for that one board, the rest of the run finishes as normal, and you're never charged for a board that came back with nothing.

#### Why is salary always empty?

Workable's public widget endpoint doesn't include pay data, so there's nothing honest to put in `salaryRaw`. If you need salary ranges, the Ashby scraper (below) passes them straight through.

### Use with AI agents (MCP)

AI agents can call this actor as a tool — **Claude Desktop, Cursor, n8n, LangGraph, CrewAI**, or any MCP-compatible client — through **Apify's hosted MCP server** at `mcp.apify.com`. An agent finds it with `search-actors`, checks its input with `fetch-actor-details`, and runs it with `call-actor`. Point your MCP client at Apify's server:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com"
    }
  }
}
```

That setup signs in with OAuth; to use a token instead, add `"headers": { "Authorization": "Bearer <YOUR_APIFY_TOKEN>" }`. The output is flat, stable JSON meant for machines to read, and agent-style pay-per-event billing is turned on.

### Integrations

Download your results as **CSV, Excel, or Google Sheets — no code needed**. Or wire it up: it works with n8n, Make, and Zapier through Apify's built-in integrations, so you can send the dataset to Slack, a webhook, a Google Sheet, or your own pipeline.

### Changelog

- **0.2.6 — 2026-07-16** — Added a public live-status link (real self-test results, no login).
- **0.2.5 — 2026-07-16** — **Filters now run over the whole board before the cap, plus honesty fixes.** *Max results per board* used to cap the raw job list *before* your keyword, location, remote, and date filters ran — so a matching job sitting past the cap could be missed. Now the filters run over the whole board first and the cap limits the *matching* jobs delivered, so a match is never hidden past the cap. Runs with no filters behave exactly as before (still the first N jobs), and per-board cost ceilings are unchanged (at most the cap × $0.001 per board — the prefilled 3-board demo still tops out around $0.15). An unreadable *Posted after* date is now rejected with a plain-English message instead of quietly switching the date filter off. The output schema table now lists `updatedAt` (always null for Workable), the actor publishes a machine-readable output schema for pipelines and agents, and the `schemaVersion` wording is corrected to a breaking-contract version (adding a field doesn't bump it). No price or count changed.
- **0.2.4 — 2026-07-16** — **Honest snapshot wording, a fix for lowercase company names, and a clearer first run.** Typing a company name in lowercase now finds the same board as typing it in normal case — before, a lowercase one-word name could be taken as a raw board token and miss the bundled listing. The page now says plainly that each run returns a fresh full snapshot (not day-to-day tracking) and points to the ATS Job Aggregator for real new-and-changed alerts; added a four-step "click to CSV" walkthrough, a chooser for picking the right WickFeed tool, and a plain "no login/API key needed, but an Apify account is" line. Troubleshooting now leads with the simple checks (filters, Max results, the run's Status and Logs) before the technical `RUN_SUMMARY` details. No price, count, or run behavior changed.
- **0.2.3 — 2026-07-16** — **Each page now speaks in its own voice.** Rewrote the shared, templated-feeling sections of this README — pricing, the output contract, the FAQ, the AI-agents (MCP) and integrations sections, and the footer — in this scraper's own plain, no-fuss voice, so it no longer reads word-for-word like the Greenhouse and Ashby pages. Every fact, price, and promise is unchanged, and nothing about how a run behaves changed.
- **0.2.2 — 2026-07-16** — **Error messages now point you to the right scraper.** Paste a careers link for a different hiring system and the message now names the product that reads it — our Greenhouse or Ashby Jobs Scraper for those, or our all-in-one Jobs Scraper + Job Monitor that covers all five systems (Greenhouse, Lever, Ashby, Workable, Recruitee) in one run; paste your company's own website and it points you to that aggregator, which can take the company name and look for the board. The Companies box now also states the first-run cost ceiling (about $0.15 for the prefilled 3-board demo). No change to how a valid run behaves.
- **0.2.1 — 2026-07-16** — **Paste a link or type a name — no token hunting.** The Companies box now accepts a pasted careers-page address (`https://apply.workable.com/capgemini-insurance`) or a plain company name (matched against the 380 bundled verified companies), alongside the bare subdomains it always took — existing setups and saved runs are unchanged. A link for a different hiring system (Greenhouse, Ashby, Lever, …), a company homepage, junk, or a name that isn't bundled is caught and reported in plain English with the exact thing to paste instead, never a silent empty run. Also: every output row now carries a `schemaVersion` field (currently `1`) and this README documents the **output contract** (existing fields are never renamed or removed within a major version; `null` means honestly-absent, not missing) — additive, so existing pipelines are unaffected. And a bare `{}` API call now runs the same three demo boards the form prefills (≈ $0.15) instead of failing, so a first call can't surprise-bill.
- **0.1.0** — Initial release. Reads Workable's public widget API (no HTML scraping), one normalized row per job, 380 verified-live boards bundled, keyword / location / remote / date filters applied after fetch, per-board failure isolation with retries and backoff, schema-validated output, and pay-per-event billing at $1 per 1,000 jobs ($0 to start a run).

### Related actors

- **Need 5 hiring systems in one feed?** The [Jobs Scraper API](https://apify.com/wickfeed/ats-job-aggregator) covers Greenhouse, Lever, Ashby, Workable and Recruitee in this same schema. Start with its **`starter-500` preset** — 500 verified-live boards in one click — and turn on **diff mode** to track only the new and changed jobs on a daily schedule (and pay **$0** on a quiet day).
- **Want published salary ranges as a field?** The [Ashby Jobs Scraper](https://apify.com/wickfeed/ashby-jobs-scraper) passes pay ranges straight through as `salaryRaw`.
- **Not sure which companies use Workable?** [ATS Company Discovery](https://apify.com/wickfeed/ats-company-discovery) finds live boards and their current open-job counts across five systems.

**Need help? Open an Issue with your run link.** If a run misbehaves or a charge looks off, open the **Issues tab** and include your run link — that's the fastest way to reach us, and we fix buyer-facing breakages the same day.

# Actor input Schema

## `preset` (type: `string`):

Optional verified board list. Leave this on "None" for the 3-company demo in the Companies box below. Switch to "All verified" for the full set of 380 live Workable boards. A preset is merged with anything you add in the Companies box (duplicates removed). The dropdown shows the maximum first-run cost at the current 50-job cap; lower "Max results per board" to reduce it.

## `sources` (type: `array`):

One company per line — however you already have it, no board-token hunting required. Paste a careers page address (like https://apply.workable.com/capgemini-insurance), type a company name (like CXG), or enter a bare board token (capgemini-insurance) — the actor works out which and finds the board reliably. A typed name is matched against the bundled list of 380 verified Workable companies (a starter directory, not every Workable company); if yours isn't in it, paste its careers page address — that always works. Optional when a preset is selected above — the two lists are merged (duplicates removed). A blank line, an address for a different hiring system, or a name that isn't in the list is skipped with a plain-English note (never fatal); the run fails only when nothing usable remains. Each board is capped at 50 jobs per run by default at $1 per 1,000 jobs, so the prefilled 3-board run tops out around $0.15.

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

Keep only jobs whose title, department or description contains ANY of these (case-insensitive). Leave empty for no keyword filtering.

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

Keep only jobs whose location contains ANY of these substrings (case-insensitive). Leave empty for no location filtering.

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

Keep only jobs Workable explicitly marks as remote (the telecommuting flag). Heads-up: jobs where Workable didn't say either way are also dropped while this is on, so a board that doesn't tag remote can come back empty — leave this off and filter by Location if you're not sure.

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

Pick a date (year-month-day, e.g. 2026-01-01). Keeps only jobs posted on or after it. Jobs with no known post date are left out while this is set, so leave it blank to keep everything. An unrecognized date is rejected with a plain-English message, never silently ignored.

## `maxResultsPerSource` (type: `integer`):

Cap on the number of MATCHING jobs delivered per board. Your keyword, location, remote and date filters run over the whole board first, then the matches are capped — so a matching job is never hidden past the cap. Defaults to 50 (matching the prefilled value), so a first run stays fast and cheap — and clearing this field falls back to 50, never a surprise larger run. Raise it once you're happy with the output.

## `includeHtml` (type: `boolean`):

Also include the original HTML job description as descriptionHtml. Off by default to keep records lean.

## Actor input object example

```json
{
  "preset": "none",
  "sources": [
    "CXG",
    "https://apply.workable.com/avomind",
    "crossbordertalents"
  ],
  "keywords": [
    "engineer",
    "product"
  ],
  "locations": [
    "remote",
    "berlin"
  ],
  "remoteOnly": false,
  "maxResultsPerSource": 50,
  "includeHtml": 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 = {
    "preset": "none",
    "sources": [
        "capgemini-insurance",
        "avomind",
        "crossbordertalents"
    ],
    "maxResultsPerSource": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("wickfeed/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 = {
    "preset": "none",
    "sources": [
        "capgemini-insurance",
        "avomind",
        "crossbordertalents",
    ],
    "maxResultsPerSource": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("wickfeed/workable-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 '{
  "preset": "none",
  "sources": [
    "capgemini-insurance",
    "avomind",
    "crossbordertalents"
  ],
  "maxResultsPerSource": 50
}' |
apify call wickfeed/workable-jobs-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Workable Jobs Scraper — API, no HTML",
        "description": "Track new Workable job postings from 380 verified boards built in — or just type a company name. Clean spreadsheet, no login. $1 per 1,000 jobs.",
        "version": "0.2",
        "x-build-id": "GOJMzGFuz3EwVXxUO"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/wickfeed~workable-jobs-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-wickfeed-workable-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/wickfeed~workable-jobs-scraper/runs": {
            "post": {
                "operationId": "runs-sync-wickfeed-workable-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/wickfeed~workable-jobs-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-wickfeed-workable-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": {
                    "preset": {
                        "title": "Company list",
                        "enum": [
                            "none",
                            "all"
                        ],
                        "type": "string",
                        "description": "Optional verified board list. Leave this on \"None\" for the 3-company demo in the Companies box below. Switch to \"All verified\" for the full set of 380 live Workable boards. A preset is merged with anything you add in the Companies box (duplicates removed). The dropdown shows the maximum first-run cost at the current 50-job cap; lower \"Max results per board\" to reduce it.",
                        "default": "none"
                    },
                    "sources": {
                        "title": "Companies (name, careers URL, or board token)",
                        "type": "array",
                        "description": "One company per line — however you already have it, no board-token hunting required. Paste a careers page address (like https://apply.workable.com/capgemini-insurance), type a company name (like CXG), or enter a bare board token (capgemini-insurance) — the actor works out which and finds the board reliably. A typed name is matched against the bundled list of 380 verified Workable companies (a starter directory, not every Workable company); if yours isn't in it, paste its careers page address — that always works. Optional when a preset is selected above — the two lists are merged (duplicates removed). A blank line, an address for a different hiring system, or a name that isn't in the list is skipped with a plain-English note (never fatal); the run fails only when nothing usable remains. Each board is capped at 50 jobs per run by default at $1 per 1,000 jobs, so the prefilled 3-board run tops out around $0.15.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "keywords": {
                        "title": "Keywords",
                        "type": "array",
                        "description": "Keep only jobs whose title, department or description contains ANY of these (case-insensitive). Leave empty for no keyword filtering.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "locations": {
                        "title": "Locations",
                        "type": "array",
                        "description": "Keep only jobs whose location contains ANY of these substrings (case-insensitive). Leave empty for no location filtering.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "remoteOnly": {
                        "title": "Remote only",
                        "type": "boolean",
                        "description": "Keep only jobs Workable explicitly marks as remote (the telecommuting flag). Heads-up: jobs where Workable didn't say either way are also dropped while this is on, so a board that doesn't tag remote can come back empty — leave this off and filter by Location if you're not sure.",
                        "default": false
                    },
                    "postedAfter": {
                        "title": "Posted after",
                        "type": "string",
                        "description": "Pick a date (year-month-day, e.g. 2026-01-01). Keeps only jobs posted on or after it. Jobs with no known post date are left out while this is set, so leave it blank to keep everything. An unrecognized date is rejected with a plain-English message, never silently ignored."
                    },
                    "maxResultsPerSource": {
                        "title": "Max results per board",
                        "minimum": 1,
                        "maximum": 100000,
                        "type": "integer",
                        "description": "Cap on the number of MATCHING jobs delivered per board. Your keyword, location, remote and date filters run over the whole board first, then the matches are capped — so a matching job is never hidden past the cap. Defaults to 50 (matching the prefilled value), so a first run stays fast and cheap — and clearing this field falls back to 50, never a surprise larger run. Raise it once you're happy with the output.",
                        "default": 50
                    },
                    "includeHtml": {
                        "title": "Include raw HTML description",
                        "type": "boolean",
                        "description": "Also include the original HTML job description as descriptionHtml. Off by default to keep records lean.",
                        "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
