# Workday Careers Site Job Listings Extractor (`nimbryxo-studio/workday-careers-site-job-listings-extractor`) Actor

Pull job postings from any company's Workday careers site: title, location, requisition ID, posting and start dates, time type, remote status and full description. Filter by keyword, location or posting date.

- **URL**: https://apify.com/nimbryxo-studio/workday-careers-site-job-listings-extractor.md
- **Developed by:** [Nimbryxo-studio](https://apify.com/nimbryxo-studio) (community)
- **Categories:** Jobs, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.49 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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

## Workday Careers Site Job Listings Extractor

Workday powers the careers sites of thousands of employers, all at URLs ending in `myworkdayjobs.com` or `myworkdaysite.com`. Point this actor at any of them and get every open role as structured records: exact posting dates, requisition IDs, all locations, job family, remote or hybrid status, time type, published salary ranges, full descriptions and apply links. No login, no API key and no proxy setup.

### What this actor does

- **Works with any public Workday careers site** - paste a careers URL, a direct job URL, or use a tenant name (its career-site ID is discovered automatically when omitted). Both `myworkdayjobs.com` and `myworkdaysite.com` URL families are supported.
- **Filters at the source** by keyword, location, job family and remote work, then applies posting-date and start-date cutoffs.
- **Enriches every job** with the full HTML and plain-text description, exact posting date, employment type, work model, every location the role is open to, and a published salary range when the employer states one.
- **Reads the whole site** - pages through all results, removes duplicates across pages and URLs, and splits large sites by job family, then by one small secondary facet such as time type or location when one family is still over Workday's per-query limit.
- **Empty fields are omitted** - a missing salary, remote type or end date is omitted from that job's record instead of being sent empty.

### Output per job

**Identity and links**

- `type` - `job_workday` for every real job record
- `title` - job title
- `id`, `requisitionId` - the requisition identifier, when the employer publishes one
- `jobPostingId` - Workday's internal posting identifier
- `url` - public job page
- `applyUrl` - the posting page where the Apply button lives
- `jobRequisitionUrl` - the employer's canonical posting URL
- `externalPath` - the job's path on its careers site

**Employer and source**

- `hiringOrganization` - the legal entity name published on the posting; the Workday tenant slug when details are off or the posting page cannot be read, and omitted when a fetched posting publishes no organization name
- `tenant`, `site`, `region` - the Workday tenant, career-site ID and data-center region the job came from

**Locations**

- `location` - primary location text
- `locations` - every location the role is open to, when the posting lists more than one
- `primaryLocation` - structured primary location, including country details
- `additionalLocations` - other locations listed on the posting
- `country`, `countryCode` - country of the primary location and its two-letter code

**Work model**

- `timeType` - full-time or part-time designation
- `employmentType` - standardized employment type such as `FULL_TIME`
- `remoteType` - the employer's own remote/hybrid label
- `workplaceType` - normalized `remote`, `hybrid`, `onsite` or `field`
- `jobLocationType` - `TELECOMMUTE` when the posting is marked remote

**Dates**

- `postedOn` - how the careers site displays the posting age
- `postingDate` - exact posting date in ISO 8601 form
- `startDate` - role start date, when published
- `endDate`, `applicationCloseDate` - application close date, when published
- `endDateText` - the employer's own end-date wording
- `applicationTimeRemaining` - time left to apply, when shown

**Description and pay**

- `jobDescription` - full HTML description
- `descriptionText` - plain-text version of the description
- `compensationRangeMin`, `compensationRangeMax` - published pay range; when a posting lists several location-specific ranges, the range for the job's primary location is used
- `compensationCurrency`, `compensationFrequency` - pay currency and hourly/monthly/yearly period
- `compensationText` - the sentence the range was read from
- `compensationType` - `range` or `single`

**Classification and extras**

- `jobFamily` - job family or category, when the site publishes one
- `canApply`, `isPosted` - whether the posting is open to applicants
- `questionnaireId`, `secondaryQuestionnaireId` - application questionnaire references, when present
- `similarJobs` - related roles, each with `title`, `url`, and available listing details
- `logoImage` - employer logo URL, when the site exposes one
- `videoInfo` - embedded recruiting video details, when present
- `scrapedAt` - ISO 8601 timestamp of the scrape

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `careerSite` | `careerSite` (careers/job URLs), `tenant` (tenant + site), or `jobDetail` (specific `/job/...` URLs). |
| `startUrls` | array | \["https://salesforce.wd12.myworkdayjobs.com/External_Career_Site"] | Workday careers-site or job URLs (mode=careerSite or jobDetail). |
| `tenant` | string | - | Workday tenant name, for example `nvidia` (mode=tenant). |
| `site` | string | - | Optional career-site ID from the URL, for example `NVIDIAExternalCareerSite` (mode=tenant). Leave it blank to discover the tenant's first public site automatically. |
| `region` | string | `auto` | Workday data-center region; `auto` detects it (mode=tenant). |
| `searchText` | string | - | Keyword passed to the site's own job search. |
| `locations` | array | `[]` | Location names such as `United States`, `New York` or `Remote`. |
| `jobFamilies` | array | `[]` | Job family names such as `Engineering` or `Sales`. |
| `remoteOnly` | boolean | `false` | Keep only postings explicitly marked remote. |
| `postedWithin` | string | `any` | `any`, `1 day`, `3 days`, `7 days`, `14 days`, `30 days`, `60 days` or `90 days`. |
| `postedAfter` | string | - | Exact cutoff date in `YYYY-MM-DD` form. |
| `startDateFrom` | string | - | Keep roles starting on or after this `YYYY-MM-DD` date. |
| `scrapeDetails` | boolean | `true` | Fetch the full description, exact date, work model and all locations. |
| `includeJobFamily` | boolean | `true` | Add the job family/category to each record. |
| `maxItems` | integer | `50` | Maximum jobs to save across all URLs (1-10,000). Jobs are returned in URL order, so a large first site can use the whole cap. |
| `proxyConfiguration` | object | proxy off | Optional. The actor works without a proxy. |

#### Example: every open role at one company

```json
{
    "mode": "careerSite",
    "startUrls": [
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"
    ],
    "maxItems": 500
}
```

#### Example: engineering roles in the United States

```json
{
    "mode": "careerSite",
    "startUrls": [
        "https://salesforce.wd12.myworkdayjobs.com/External_Career_Site"
    ],
    "searchText": "engineer",
    "locations": ["United States"],
    "jobFamilies": ["Engineering"],
    "postedWithin": "14 days",
    "maxItems": 200
}
```

#### Example: by tenant name, no URL

```json
{
    "mode": "tenant",
    "tenant": "workday",
    "site": "Workday",
    "locations": ["Remote"],
    "scrapeDetails": true,
    "maxItems": 50
}
```

`site` is optional. When it is omitted, the actor reads the tenant's public `robots.txt` and uses the first career site that responds.

#### Example: one specific posting

```json
{
    "mode": "jobDetail",
    "startUrls": [
        "https://salesforce.wd12.myworkdayjobs.com/External_Career_Site/job/Spain---Madrid/Deployment-Strategist---Spanish-Speaker_JR366417"
    ],
    "scrapeDetails": true
}
```

#### Example: a myworkdaysite.com careers site

```json
{
    "mode": "careerSite",
    "startUrls": [
        "https://wd1.myworkdaysite.com/en-US/recruiting/fmr/FidelityCareers"
    ],
    "searchText": "planning",
    "maxItems": 100
}
```

### Use cases

- **Talent sourcing** - collect every open role at target employers, with locations and apply links, for outreach or a CRM.
- **Competitive hiring intelligence** - track which teams, offices and job families a competitor is expanding.
- **Compensation benchmarking** - gather published salary ranges by title, family and location.
- **Job-board aggregation** - feed Workday postings from many employers into your own listings or alerts.
- **Labor-market research** - measure remote/hybrid share, time type and posting velocity across companies.
- **Recruiting operations** - monitor a company's careers site on a schedule and diff by requisition ID.

### FAQ

**Does this work with any company that uses Workday?**
Yes. Any public careers site on `myworkdayjobs.com` or `myworkdaysite.com` works the same way. Paste that careers URL, or use `tenant` with an optional `site`.

**How do I find the tenant and career-site ID?**
Both are in the careers URL. In `https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite`, the tenant is `nvidia`, the region is `wd5` and the site is `NVIDIAExternalCareerSite`. The site ID is case-sensitive, but you can omit it: the actor discovers the tenant's first public site from its `robots.txt`.

**Why did I get fewer jobs than the company lists?**
Workday returns at most about 2,000 results for a single search. The actor splits a capped site by job family, and splits a single large family again by one small secondary facet (usually time type) so most sites are read fully. If one slice is still above the cap, narrow the run with `searchText`, `locations` or `postedWithin` and run it more than once.

**Why are some fields missing from a job?**
Employers publish different details. Salary ranges, remote or hybrid labels, end dates, logos and similar jobs appear only when the posting includes them. Missing fields are omitted, never sent as null.

**Why is `jobFamily` missing on some sites?**
A few employers do not publish a job-family/category filter at all. For those sites there is no reliable source for the field, so it is omitted rather than guessed. Setting `includeJobFamily` to `false` also omits it, including on large sites that are split by job family to get past the 2,000-result limit.

**Which salary range is used when a posting lists several?**
When the posting labels ranges by location, the actor uses the range that matches the job's primary location. If no location-specific range applies, it uses the posting's typical/base range. Values are never estimated.

**What is the difference between `scrapeDetails` on and off?**
With it on, each job's public page is read for the full description, the exact posting date, employment type, work model and every location. With it off, you get the fast listing fields: title, location, requisition ID, posting age and URL. A `30+ Days Ago` posting has no exact date until details are on.

**How do I scrape several companies in one run?**
Paste all of their careers URLs and set `maxItems` large enough to cover the total. Jobs are returned in URL order, so a site with more jobs than `maxItems` can use the whole cap; split the run by company if you need equal coverage.

**Why did a very old date cutoff return fewer jobs than expected?**
Workday has no server-side date filter, so dates are checked on the postings the site returns, newest first. To avoid reading an entire large site for a sparse cutoff, the actor stops after 30 pages with no match. Narrow the run with `searchText`, `locations` or `jobFamilies` so the matching roles are reached sooner.

**Can I collect only new jobs?**
Schedule the actor and compare `requisitionId` (or `externalPath`) between runs. The actor returns the current postings each time; it does not keep state between runs.

**Does it return localized job text?**
Job titles and descriptions are the employer's own text. Workday's public API serves the site's default language and ignores locale headers or query parameters, so the actor does not offer a language switch.

**Does it work with remote-only searches?**
Yes. `remoteOnly` keeps postings the employer explicitly marks remote. Hybrid and onsite postings are excluded.

**Do I need a proxy, login or API key?**
No. The actor reads public careers pages and works without any of them. Leave the proxy setting off unless you need a specific connection setup.

**Why is `hiringOrganization` sometimes a legal entity name?**
That is the employer name Workday publishes on the posting. Some companies use a legal subsidiary name rather than the consumer brand. When a fetched posting publishes no organization name, the field is omitted instead of guessing a brand; listing-only runs use the Workday tenant slug.

**Is this affiliated with Workday or the employers whose jobs it returns?**
No. This is an independent, third-party actor that reads each company's own public careers site. It is not affiliated with or endorsed by Workday, Inc. or any employer listed.

# Actor input Schema

## `mode` (type: `string`):

How to find jobs. 'Scrape career site URLs' accepts careers pages or job URLs. 'Scrape a tenant by name' uses tenant + site. 'Scrape specific job URLs' requires /job/... URLs in startUrls.

## `startUrls` (type: `array`):

Public Workday careers-site or job URLs (mode=careerSite or jobDetail). Paste the URL from your browser; both myworkdayjobs.com and myworkdaysite.com are supported. In careerSite mode a careers URL scrapes the site's jobs and a /job/... URL scrapes that single posting; in jobDetail mode use a /job/... URL.

## `tenant` (type: `string`):

Workday tenant name, for example 'nvidia' or 'capitalone' (mode=tenant). You can also paste the full careers URL here or use 'tenant/site'. When the site ID is omitted, the actor finds the tenant's first public site automatically.

## `site` (type: `string`):

Optional career site identifier shown in the URL after the tenant host, for example 'NVIDIAExternalCareerSite' or 'External_Career_Site' (mode=tenant). It is case-sensitive. Leave blank to discover the tenant's first public site automatically.

## `region` (type: `string`):

Workday data-center region. Leave 'auto' to detect it, or set wd1, wd3, wd5, wd12, wd103, and similar when you already know it (mode=tenant).

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

Optional keyword passed to the site's own job search, for example 'engineer' or 'marketing'. Workday searches titles and descriptions.

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

Optional locations to keep. Use names such as 'United States', 'New York', 'Remote' or 'US, CA, Santa Clara'; the actor matches them against the site's own location filters. Facet IDs are also accepted.

## `jobFamilies` (type: `array`):

Optional job families or categories to keep, for example 'Engineering', 'Sales' or 'Finance'. Names come from the site's own Job Category filter; IDs are also accepted.

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

Keep only postings the employer explicitly marks as remote. Hybrid and onsite postings are excluded. This turns on full detail fetching.

## `postedWithin` (type: `string`):

Keep jobs posted within this window. 'Any time' applies no date filter. Use Posted After for an exact cutoff date.

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

Optional exact cutoff date in YYYY-MM-DD form. When both Posted Within and Posted After are set, the stricter cutoff wins.

## `startDateFrom` (type: `string`):

Optional YYYY-MM-DD cutoff for the role's start date. Only applies when the posting publishes a start date. This turns on full detail fetching.

## `scrapeDetails` (type: `boolean`):

Fetch each posting's public job page for the full description, exact posting date, employment type, work model and every location. Turn off for a fast listing-only run (title, location, requisition ID, posting label and URL). Direct job URLs always fetch details because a listing has no record for them.

## `includeJobFamily` (type: `boolean`):

Add each job's family or category (for example Engineering or Sales). This uses the site's own Job Category filter and is skipped automatically when a site has no such filter.

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

Maximum number of jobs to save across all URLs. Jobs are returned in URL order, so a large first site can use the whole cap.

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

Optional. The actor works without a proxy and chooses a working connection automatically; change this only if you need a specific proxy setup.

## Actor input object example

```json
{
  "mode": "careerSite",
  "startUrls": [
    "https://salesforce.wd12.myworkdayjobs.com/External_Career_Site"
  ],
  "region": "auto",
  "locations": [],
  "jobFamilies": [],
  "remoteOnly": false,
  "postedWithin": "any",
  "scrapeDetails": true,
  "includeJobFamily": true,
  "maxItems": 3,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Dataset containing all scraped job postings.

# 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 = {
    "mode": "careerSite",
    "startUrls": [
        "https://salesforce.wd12.myworkdayjobs.com/External_Career_Site"
    ],
    "region": "auto",
    "locations": [],
    "jobFamilies": [],
    "remoteOnly": false,
    "postedWithin": "any",
    "scrapeDetails": false,
    "includeJobFamily": false,
    "maxItems": 3,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("nimbryxo-studio/workday-careers-site-job-listings-extractor").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 = {
    "mode": "careerSite",
    "startUrls": ["https://salesforce.wd12.myworkdayjobs.com/External_Career_Site"],
    "region": "auto",
    "locations": [],
    "jobFamilies": [],
    "remoteOnly": False,
    "postedWithin": "any",
    "scrapeDetails": False,
    "includeJobFamily": False,
    "maxItems": 3,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("nimbryxo-studio/workday-careers-site-job-listings-extractor").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 '{
  "mode": "careerSite",
  "startUrls": [
    "https://salesforce.wd12.myworkdayjobs.com/External_Career_Site"
  ],
  "region": "auto",
  "locations": [],
  "jobFamilies": [],
  "remoteOnly": false,
  "postedWithin": "any",
  "scrapeDetails": false,
  "includeJobFamily": false,
  "maxItems": 3,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call nimbryxo-studio/workday-careers-site-job-listings-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nimbryxo-studio/workday-careers-site-job-listings-extractor"
        }
    }
}
```

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/vBZKUgBIGEdKTY5mi/builds/L7eadpJIq6UsaeicD/openapi.json
