# Workday Jobs Scraper — Company Careers, No API Key (`flash_scraper/workday-jobs-scraper`) Actor

Workday jobs scraper: live openings from any company hiring through Workday. Paste a myworkdayjobs.com careers URL or just a company name - get title, location, salary (parsed, annualized), exact posting date, requisition ID and full description. Only-new-jobs mode turns a schedule into a job alert.

- **URL**: https://apify.com/flash\_scraper/workday-jobs-scraper.md
- **Developed by:** [Flash Scrape](https://apify.com/flash_scraper) (community)
- **Categories:** Jobs, 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 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/platform/actors/running/actors-in-store#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 — Company Careers, No API Key

Live job openings from **any company that hires through Workday** — NVIDIA, Salesforce, Adobe and tens of thousands of others. Paste the company's `myworkdayjobs.com` careers URL (always works) or just type a company name like `nvidia` (auto-discovered), and get every live posting as a clean row: title, location, remote, employment type, **salary range parsed from the posting and annualized**, exact posting date, requisition ID and the full description.

No API key, no login, no proxy, no headless browser — the actor calls the same public JSON endpoint the company's own careers page uses, so the data is exactly what a candidate sees, at the moment you run it.

> Also hiring on Greenhouse, Lever or Ashby? → [ATS Job Scraper](https://apify.com/flash_scraper/ats-job-scraper).
> Need LinkedIn, Indeed and Glassdoor too — merged and deduplicated across 12 boards with only-new-jobs monitoring? → [Multi Job Board Scraper](https://apify.com/flash_scraper/multi-jobboard-scraper)

### What you get

One row per live opening. Measured on the default run (NVIDIA + Salesforce + Adobe, 100 rows, 2026-08-15):

| column | fill | notes |
|---|---|---|
| `company`, `tenant`, `site` | 100% | which careers site the row came from |
| `title`, `location`, `url` | 100% | canonical public posting URL |
| `employment_type` | 100% | "Full time" / "Part time" (from the posting detail) |
| `job_req_id` | 100% | the requisition ID recruiters use (e.g. `R171155`) |
| `posted_at` | 100% | exact date from the posting detail (e.g. `2026-08-14`) |
| `posted_text` | 100% | Workday's own wording ("Posted Yesterday") |
| `description`, `description_snippet` | 100% | full text + first 300 chars |
| `salary_min` / `salary_max` / `salary_currency` / `salary_interval` | 33% | **only when the posting itself states a range** — parsed from the text, hourly/monthly figures annualized, never guessed |
| `remote` | 34% | `true` when the posting says remote; `null` when there is no evidence — never guessed |

Example row (real, from the default run):

```json
{
  "company": "adobe",
  "tenant": "adobe",
  "site": "external_experienced",
  "title": "Senior Product Manager",
  "location": "San Jose",
  "remote": null,
  "employment_type": "Full time",
  "job_req_id": "R171155",
  "salary_min": 165600,
  "salary_max": 239725,
  "salary_currency": "USD",
  "salary_interval": "yearly",
  "url": "https://adobe.wd5.myworkdayjobs.com/en-US/external_experienced/job/San-Jose/Senior-Product-Manager_R171155",
  "source": "workday",
  "posted_at": "2026-08-14",
  "posted_text": "Posted Yesterday",
  "description_snippet": "About the role – Adobe.com reaches millions of customers…",
  "description": "…full posting text…"
}
```

### Quick start

Run it with no input at all — you get up to 100 live jobs from the three sample companies. Then put your own targets in:

```json
{
  "companies": ["nvidia", "coinbase"],
  "workdayUrls": ["https://adobe.wd5.myworkdayjobs.com/en-US/external_experienced"],
  "searchText": "machine learning",
  "maxItems": 200
}
```

**URL or name?** A pasted `myworkdayjobs.com` URL always works — it names the tenant and site exactly. A bare company name is auto-discovered (the actor probes Workday's hosts and the site slugs customers actually use, and caches the answer for future runs); discovery is best-effort — when it can't find the site, the run tells you exactly which company to paste a URL for, and never bills you for it.

### Input reference

| field | default | what it does |
|---|---|---|
| `companies` | 2-company sample | Company names, auto-discovered. Your list replaces the sample entirely. |
| `workdayUrls` | 1-URL sample | Any `myworkdayjobs.com` URL of the careers site — the reliable path. |
| `searchText` | `""` | Searched **server-side by Workday itself**, like the careers page's own search box. |
| `locationContains` | `""` | Keep only jobs whose location contains this text. Applied before billing. |
| `remoteOnly` | `false` | Keep only jobs with remote evidence (location/title/posting flag). Never guessed. |
| `postedWithinDays` | `0` (off) | Keep only jobs posted in the last N days ("30+ Days Ago" counts as 31; undated jobs are kept, never guessed away). |
| `onlyNewJobs` | `false` | Job-alert mode — see below. |
| `maxItems` | `100` | Total cap across ALL companies, split round-robin so one giant tenant can't eat the budget. Your cost ceiling. |
| `fetchDescriptions` | `true` | Fetch each delivered job's detail: full description, exact date, employment type, req ID, salary. One extra request per delivered row — same price per row. |

Every filter runs **before billing** — a filtered job is never charged.

### 🔔 Job alerts: `onlyNewJobs` + a schedule

Schedule the actor (daily or hourly) with `onlyNewJobs: true` and the same companies + filters:

- the **first run is the baseline** — it delivers everything and says so;
- every later run delivers **only postings not seen before**;
- a run where nothing is new delivers nothing, **bills nothing**, and says "Nothing new" plainly.

Watch memory lives in a named key-value store (`workday-jobs-monitor`) in your own account, pruned automatically (90 days / 50k keys). Point the run at Slack/email with a webhook and you have a hiring-signal feed for sales, recruiting or job hunting — companies posting new roles are companies with budget.

### Use it from your code

```javascript
// JavaScript — apify-client
const { ApifyClient } = require('apify-client');
const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('flash_scraper/workday-jobs-scraper').call({
  companies: ['nvidia'], searchText: 'engineer', maxItems: 100,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

```python
## Python — apify-client
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("flash_scraper/workday-jobs-scraper").call(run_input={
    "companies": ["nvidia"], "searchText": "engineer", "maxItems": 100})
items = client.dataset(run["defaultDatasetId"]).list_items().items
```

```bash
## curl — run synchronously and get the dataset back
curl -X POST "https://api.apify.com/v2/acts/flash_scraper~workday-jobs-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"companies": ["nvidia"], "maxItems": 50}'
```

### n8n / Make / Zapier

All three have a native Apify node/module: pick **Run actor** → `flash_scraper/workday-jobs-scraper`, pass the JSON input above, and read the default dataset when the run finishes. The `onlyNewJobs` mode pairs perfectly with a schedule trigger — new postings flow straight into a Slack message, a Google Sheet or your CRM, and quiet days cost you nothing.

### Honest limits

- **Workday customers only.** If a company hires through Greenhouse/Lever/Ashby, use [ATS Job Scraper](https://apify.com/flash_scraper/ats-job-scraper); for LinkedIn/Indeed/Glassdoor use [Multi Job Board Scraper](https://apify.com/flash_scraper/multi-jobboard-scraper).
- **Bare-name discovery is best-effort.** It resolves common setups (measured: nvidia, salesforce, spotify-style slugs); unusual site names need the careers URL pasted once — the run names exactly which company needs it.
- **Custom career domains** (careers.company.com) hide the tenant — paste the `myworkdayjobs.com` address that page actually loads.
- **Salary only when stated.** ~1 in 3 postings on the sample companies state a range (mostly US postings, where it's legally required); rows without one carry `null`, never a guess.
- `remote` is evidence-based: `true` only when the posting says so, `null` otherwise.
- Workday reports posting age coarsely past 30 days ("Posted 30+ Days Ago"); with `fetchDescriptions` on (the default) `posted_at` is the exact date from the posting detail.

### Related actors

- [ATS Job Scraper — Greenhouse, Lever & Ashby](https://apify.com/flash_scraper/ats-job-scraper)
- [Multi Job Board Scraper — LinkedIn, Indeed, Glassdoor + 9 more](https://apify.com/flash_scraper/multi-jobboard-scraper)
- [Remote Job Aggregator — 10 boards, one feed](https://apify.com/flash_scraper/remote-job-aggregator)
- [LinkedIn Jobs Scraper — $0.50 per 1,000 jobs](https://apify.com/flash_scraper/linkedin-jobs-scraper)

# Actor input Schema

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

Company names, one per line, e.g. 'nvidia', 'salesforce', 'adobe'. The actor finds each company's Workday tenant automatically (best-effort - a pasted URL below is the reliable path). Supplying your own list replaces the sample entirely.

## `workdayUrls` (type: `array`):

Any myworkdayjobs.com URL of the company's careers site - the address bar of their jobs page, e.g. 'https://nvidia.wd5.myworkdayjobs.com/en-US/NVIDIAExternalCareerSite'. Works for every Workday customer, no discovery needed.

## `searchText` (type: `string`):

Searched server-side by Workday itself, exactly like typing in the careers page's search box, e.g. 'software engineer'. Leave empty for every opening.

## `locationContains` (type: `string`):

Only keep jobs whose location contains this text (case-insensitive), e.g. 'Remote', 'San Francisco', 'London'. Leave empty for every location.

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

Only keep jobs whose posting says remote (in the location, title or the posting's own remote flag). Jobs with no remote evidence are dropped, never guessed.

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

Only keep jobs posted within the last N days (Workday reports posting age as 'Posted 7 Days Ago'; '30+ Days Ago' counts as 31). 0 = no age filter. Jobs whose age Workday doesn't state are kept, never guessed away.

## `onlyNewJobs` (type: `boolean`):

The first run is the baseline (delivers everything and says so). Every later run with the same companies + filters delivers ONLY postings that were not seen before; a run where nothing is new delivers nothing, bills nothing, and says 'Nothing new' plainly. Memory lives in a named key-value store ('workday-jobs-monitor') in your own account.

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

Total cap across ALL companies in the run, split round-robin so one giant tenant cannot eat the whole budget. Your cost ceiling.

## `fetchDescriptions` (type: `boolean`):

Fetch each delivered job's detail page: full description text, exact posting date, employment type, requisition ID, and the salary range parsed from the posting (annualized). One extra request per delivered job - same price per row.

## Actor input object example

```json
{
  "companies": [
    "nvidia",
    "salesforce"
  ],
  "workdayUrls": [
    "https://adobe.wd5.myworkdayjobs.com/en-US/external_experienced"
  ],
  "searchText": "",
  "locationContains": "",
  "remoteOnly": false,
  "postedWithinDays": 0,
  "onlyNewJobs": false,
  "maxItems": 50,
  "fetchDescriptions": true
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# 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": [
        "nvidia",
        "salesforce"
    ],
    "workdayUrls": [
        "https://adobe.wd5.myworkdayjobs.com/en-US/external_experienced"
    ],
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("flash_scraper/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 = {
    "companies": [
        "nvidia",
        "salesforce",
    ],
    "workdayUrls": ["https://adobe.wd5.myworkdayjobs.com/en-US/external_experienced"],
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("flash_scraper/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 '{
  "companies": [
    "nvidia",
    "salesforce"
  ],
  "workdayUrls": [
    "https://adobe.wd5.myworkdayjobs.com/en-US/external_experienced"
  ],
  "maxItems": 50
}' |
apify call flash_scraper/workday-jobs-scraper --silent --output-dataset

```

## MCP server setup

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