# Workday Jobs Scraper — every role from a Workday careers site (`plainapi/workday-jobs-scraper`) Actor

Get every open role from any Workday careers site. Reads the official public job-board API that the company's own careers page uses — no browser, no cookies, no blocking. Handles boards with thousands of roles.

- **URL**: https://apify.com/plainapi/workday-jobs-scraper.md
- **Developed by:** [Shun Furu](https://apify.com/plainapi) (community)
- **Categories:** Jobs, Developer tools, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 job results

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

## Workday Jobs Scraper

Get every open role from any Workday careers site.

Paste the careers URL — `https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite` — and this
Actor reads the **official public job-board API that the company's own careers page calls**, and
returns clean, flat JSON.

No browser. No cookies. No proxies. No blocking.

```
Input:   ["https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"]
Output:  2,000 rows — title, location, remote flag, requisition ID, URL
```

### Why this one

Workday runs the careers site of a large share of the world's biggest employers, and those boards
are big: NVIDIA publishes about **2,000** open roles, Salesforce about **1,530**, Cisco about
**1,180** (measured 2026-08-22).

Most scrapers render those pages in a headless browser and parse HTML, which is slow, gets blocked,
and breaks whenever the page changes. This Actor talks to the same JSON endpoint the page itself
uses, so it is fast and it does not break.

Workday returns **20 roles per request**. A 2,000-role board is therefore 100 requests. This Actor
reads the total up front and fetches the remaining pages **in parallel**, which takes a full
2,000-role board from minutes down to about **16 seconds**.

### Input

| Field | Type | Default | What it does |
|---|---|---|---|
| `careerSites` | array of strings | one example site | Workday careers URLs. A link to a single job works too — the site is taken from it |
| `keyword` | string | — | Keep only roles whose title matches any of these words |
| `location` | string | — | Keep only roles whose location contains any of these words |
| `remoteOnly` | boolean | `false` | Keep only roles whose location mentions remote |
| `includeDescription` | boolean | `false` | Also fetch each role's detail page — see below |
| `maxJobsPerSite` | integer | `0` (no limit) | Cap roles per site |
| `maxTotalJobs` | integer | `0` (no limit) | Cap the whole run — use this to cap cost |

#### Finding the careers URL

Open the company's job search page. If the address bar shows
`something.wd`*n*`.myworkdayjobs.com/SiteName`, that is the URL to paste. Some employers put a
branded domain in front of it (`jobs.example.com`); in that case, click through to a single job and
copy the `myworkdayjobs.com` URL that appears.

> The Workday tenant cannot be derived from a company domain — `nvidia.com` gives no hint that the
> board lives at `nvidia.wd5.myworkdayjobs.com`. That is why this Actor asks for the URL rather
> than pretending to guess.

#### About `includeDescription`

Workday's listing endpoint is deliberately thin. It gives the title, location, requisition ID and a
**relative** date (`Posted Yesterday`, returned as `postedLabel`).

Turn `includeDescription` on and the Actor also reads each role's detail page, which adds:

- `description` — the full job description as plain text
- `publishedAt` — a real ISO date
- `employmentType` — e.g. `Full time`

That is one extra request per role, so on a 2,000-role board it is much slower. Pair it with
`maxJobsPerSite` when you only need details for the newest roles.

### Output

```json
{
  "careersSite": "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
  "tenant": "nvidia",
  "workdayHost": "nvidia.wd5.myworkdayjobs.com",
  "siteName": "NVIDIAExternalCareerSite",
  "jobId": "JR2019870",
  "title": "Senior Systems Software Engineer, Data Center Platform Enablement",
  "url": "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite/job/US-CA-Santa-Clara/...",
  "location": "US, CA, Santa Clara",
  "remote": null,
  "employmentType": "",
  "publishedAt": null,
  "postedLabel": "Posted Yesterday",
  "scrapedAt": "2026-08-22T09:48:35.371Z"
}
```

A `SUMMARY` record is written to the key-value store listing every site that was read, the tenant
and site name it resolved to, and how many roles matched your filters.

### Pricing

You pay for roles, not for attempts.

| | Price |
|---|---|
| Starting a run | **$0.00001** (one US cent per 1,000 runs — effectively nothing) |
| Each role returned | **$0.002** ($2 per 1,000 roles) |

If a URL cannot be read, no rows are produced, so there is nothing to pay for. Errors are written
to the log and to `SUMMARY`, never to the dataset, specifically so a failed run does not appear on
your bill.

A full 2,000-role board costs about **$4**. Use `maxTotalJobs` to cap a run.

### Typical uses

- **Talent intelligence** — watch which teams a large employer is growing, and where.
- **Job aggregators** — pull a curated list of big employers on a schedule.
- **Market research** — measure hiring velocity across an industry over time.
- **Job seekers** — track a shortlist of employers and catch roles the day they open.

### Notes on data and compliance

- Only the **public, unauthenticated** job-board endpoint is used. Nothing behind a login is touched.
- Job postings are **company business information, not personal data**. No candidate or employee
  data is collected.
- No bot protection is bypassed and no rate limits are circumvented; the Actor backs off on `429`.

### Limitations — stated up front

- **A careers URL is required.** A bare company domain is not enough, for the reason given above.
- `publishedAt` and `employmentType` are empty unless `includeDescription` is enabled — Workday
  does not put them in the listing.
- `location` is free text as the employer wrote it (`US, CA, Santa Clara`, or `2 Locations` when a
  role spans several). It is not normalised.
- Salary is not published in Workday's public endpoints, so it is not returned.

### Other ATS platforms

If the company is not on Workday, use
**[Company Jobs Scraper](https://apify.com/plainapi/greenhouse-workday-ashby-lever-jobs-scraper)** — same approach, for
Greenhouse, Ashby, Lever, SmartRecruiters, Rippling and Personio, and it detects the platform from
a company domain.

# Actor input Schema

## `careerSites` (type: `array`):

Workday careers-site URLs, e.g. https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite — copy it from the company's job search page. A job URL works too; the site is taken from it.

## `keyword` (type: `string`):

Keep only roles whose title contains any of these words (space or comma separated). Leave empty for all roles.

## `location` (type: `string`):

Keep only roles whose location contains any of these words. Workday reports locations as free text, e.g. 'US, CA, Santa Clara'.

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

Keep only roles whose location mentions remote.

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

Workday's listing only returns a relative date ('Posted Yesterday'). Turn this on to fetch each role's detail page, which adds the full description, a real publishedAt date and the employment type. Costs one extra request per role, so it is slower on large boards.

## `maxJobsPerSite` (type: `integer`):

0 means no limit. Large employers publish thousands of roles — cap this to control cost.

## `maxTotalJobs` (type: `integer`):

0 means no limit. A hard ceiling for the whole run.

## Actor input object example

```json
{
  "careerSites": [
    "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
    "https://salesforce.wd12.myworkdayjobs.com/External_Career_Site"
  ],
  "remoteOnly": false,
  "includeDescription": false,
  "maxJobsPerSite": 0,
  "maxTotalJobs": 0
}
```

# Actor output Schema

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

Every open role found on the given Workday careers sites.

## `jobsCsv` (type: `string`):

The same rows as CSV, for spreadsheets.

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

Which tenant and site each URL resolved to, and how many roles matched.

# 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 = {
    "careerSites": [
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
        "https://salesforce.wd12.myworkdayjobs.com/External_Career_Site"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("plainapi/workday-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 = { "careerSites": [
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
        "https://salesforce.wd12.myworkdayjobs.com/External_Career_Site",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("plainapi/workday-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 '{
  "careerSites": [
    "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
    "https://salesforce.wd12.myworkdayjobs.com/External_Career_Site"
  ]
}' |
apify call plainapi/workday-jobs-scraper --silent --output-dataset

```

## MCP server setup

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