How to Find a Company's Job Board and ATS (Workday, Greenhouse, Lever, Ashby)

Uses Career Site Jobs — Workday, Greenhouse, Lever & Ashby Scraper

Short answer: Open any job on the company's careers page and look at the host: myworkdayjobs.com, greenhouse.io, lever.co, ashbyhq.com and similar tell you the ATS. Pass that URL (or an ats:slug shortcut) to Career Site Jobs and you get every open role in one schema.

Most company careers pages are a thin wrapper around an applicant tracking system. The 'Careers' link on the main site might look custom, but the job listings and apply buttons usually live on a Workday, Greenhouse, Lever or Ashby board, and that board is where the clean, current data is.

Knowing which ATS a company uses matters if you want its jobs in bulk. Each system has its own URL pattern and its own public feed, Workday hides real posting dates behind labels like 'Posted 30+ Days Ago', and job boards that copy the listings can lag or drop fields such as salary.

This guide shows how to identify the ATS from a careers URL, when you can skip that step by using the built-in index, how to feed boards into the actor, and what to do when a company uses a system that is not supported.

Step by step

  1. Open a job from the company's careers page

    Go to the company's careers page and click into any single job. The address bar or the apply button usually reveals the real board: adobe.wd5.myworkdayjobs.com/external_experienced, boards.greenhouse.io/gusto, jobs.lever.co/spotify or jobs.ashbyhq.com/amplitude. Copy the URL up to the company's board, not the individual job.

  2. Identify the ATS from the host name

    The host is enough to classify the board. The function below maps the nine systems the actor supports, including EU Greenhouse and Lever hosts, and returns None for anything else, such as SmartRecruiters or a fully custom careers site.

    from urllib.parse import urlparse
    
    ATS_HOSTS = [
        ("myworkdayjobs.com", "workday"),
        ("greenhouse.io", "greenhouse"),
        ("lever.co", "lever"),
        ("ashbyhq.com", "ashby"),
        ("workable.com", "workable"),
        ("recruitee.com", "recruitee"),
        ("teamtailor.com", "teamtailor"),
        ("jobs.personio.de", "personio"),
        ("jobs.personio.com", "personio"),
        ("bamboohr.com", "bamboohr"),
    ]
    
    
    def detect_ats(url):
        if "://" not in url:
            url = "https://" + url
        host = (urlparse(url).hostname or "").lower()
        for suffix, ats in ATS_HOSTS:
            if host == suffix or host.endswith("." + suffix):
                return ats
        return None
    
    
    for u in [
        "https://adobe.wd5.myworkdayjobs.com/external_experienced",
        "https://job-boards.greenhouse.io/gusto",
        "jobs.lever.co/spotify",
        "https://careers.example.com/jobs",
    ]:
        print(u, "->", detect_ats(u))
  3. Skip the detective work for indexed companies

    The actor ships with an index of 811 Greenhouse, Lever and Ashby companies, YC startups plus well-known employers. For those you can simply put the company name or domain into companies and the actor resolves the board itself. Or set searchAllCompanies to true and filter by keywords and locations to find every indexed company hiring for a role, without naming any of them. Workday and the other ATS always need the careers URL; the actor never guesses slugs.

    {
      "searchAllCompanies": true,
      "ats": ["ashby"],
      "keywords": ["data engineer"],
      "remoteOnly": true,
      "maxJobs": 300
    }
  4. Use the ats:slug shortcut when you know the board name

    If you already know a company's board slug, you can write it as ats:slug instead of a full URL, for example greenhouse:gusto. This is handy when you keep a list of target companies in a spreadsheet with one column for the ATS and one for the slug.

  5. Pull every open job and confirm the ATS

    Run the actor with your list. Each output row carries an ats field, so you can confirm which system each company's jobs came from, and a jobUrl that points to the original posting. Postings from different systems share one schema: title, company, department, team, location, workplace type, salary where published and posted date. Turn on includeDescription if you need the full text; it costs nothing extra.

  6. Keep a watch on new roles

    To follow a set of companies over time, schedule the run and set postedWithinDays so each run returns only recently published jobs. The snippet groups a run's results by company and ATS so you can see who is hiring most.

    import os
    from collections import Counter
    
    from apify_client import ApifyClient
    
    client = ApifyClient(os.environ["APIFY_TOKEN"])
    run = client.actor("actor-forge/career-site-jobs").call(run_input={
        "companies": [
            "greenhouse:gusto",
            "https://jobs.lever.co/spotify",
            "https://adobe.wd5.myworkdayjobs.com/external_experienced",
        ],
        "postedWithinDays": 7,
        "maxJobs": 500,
    })
    
    counts = Counter()
    for job in client.dataset(run["defaultDatasetId"]).iterate_items():
        counts[(job.get("companyName"), job.get("ats"))] += 1
    
    for (company, ats), n in counts.most_common():
        print(f"{company} ({ats}): {n} new jobs")
  7. Know what to do when the ATS is not supported

    If detect_ats returns None, the company uses something the actor cannot read, such as SmartRecruiters or a custom-built careers page. Those companies are skipped and not charged. For them you would need a general web scraper or a job board that aggregates their listings.

Sample input

{
  "companies": [
    "greenhouse:gusto",
    "https://jobs.lever.co/spotify",
    "https://jobs.ashbyhq.com/amplitude",
    "https://adobe.wd5.myworkdayjobs.com/external_experienced"
  ],
  "keywords": [
    "engineer"
  ],
  "maxJobs": 200
}

Sample output

Jobs from Workday, Ashby, Greenhouse and Lever boards come back side by side in one schema:

titlecompanyNameatslocationworkplaceTypesalaryTextpostedAtjobUrl
Sr. Manager Risk & ControlsAdobeworkdaySan Jose; Seattle2026-10-16https://adobe.wd5.myworkdayjobs.com/external_experienced/job/San-Jose/…
Customer Support Developer (Databases)AirbyteashbyUnited Statesremote$99K - $115K2026-10-08https://jobs.ashbyhq.com/airbyte/9d81a132-…
Benefits Advising (Renewals) LeaderGusto, Inc.greenhouseDenver, CO - Hybridhybrid2026-07-29https://job-boards.greenhouse.io/gusto/jobs/8078212
Art Director - MexicoSpotifyleverMexico Cityhybrid2026-10-…https://jobs.lever.co/spotify/223f9722-…

Run it from code

cURL

curl -X POST "https://api.apify.com/v2/acts/actor-forge~career-site-jobs/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"companies": ["greenhouse:gusto", "https://jobs.lever.co/spotify", "https://jobs.ashbyhq.com/amplitude", "https://adobe.wd5.myworkdayjobs.com/external_experienced"], "keywords": ["engineer"], "maxJobs": 200}'

JavaScript (Node.js)

// Node.js 18+ (built-in fetch). Set APIFY_TOKEN in your environment.
const input = {
  "companies": [
    "greenhouse:gusto",
    "https://jobs.lever.co/spotify",
    "https://jobs.ashbyhq.com/amplitude",
    "https://adobe.wd5.myworkdayjobs.com/external_experienced"
  ],
  "keywords": [
    "engineer"
  ],
  "maxJobs": 200
};

const res = await fetch(
  "https://api.apify.com/v2/acts/actor-forge~career-site-jobs/run-sync-get-dataset-items",
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.APIFY_TOKEN}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(input),
  }
);
const items = await res.json();
console.log(items.length, items[0]);

Python

# pip install apify-client   (set APIFY_TOKEN in your environment)
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run_input = {
    "companies": [
        "greenhouse:gusto",
        "https://jobs.lever.co/spotify",
        "https://jobs.ashbyhq.com/amplitude",
        "https://adobe.wd5.myworkdayjobs.com/external_experienced"
    ],
    "keywords": [
        "engineer"
    ],
    "maxJobs": 200
}

run = client.actor("actor-forge/career-site-jobs").call(run_input=run_input)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

The run-sync-get-dataset-items endpoint waits for the run (up to 5 minutes) and returns the dataset rows directly. For longer runs, start the run asynchronously and read the dataset when it finishes, as the Python example does. Replace APIFY_TOKEN with your own token from the Apify console.

What it costs

Pulling 200 engineering jobs from four company boards costs 200 x $0.003 = $0.60. A full index scan for remote data roles of about 400 jobs comes to roughly $1.20.

Charged forWhenPricePer 1,000Worked example
Job resultCharged per job posting delivered (description included at no extra cost)$0.003$3100 jobs = $0.30; 1,000 jobs = $3; a full index scan for remote data roles (~400 jobs) ≈ $1.20
Actor Start (platform start fee)Charged when the Actor starts running. Number of events charged depends on Actor memory (one event per GB, minimum one event).$0.00005—One run at 1 GB = $0.00005

Ready to try it? Career Site Jobs — Workday, Greenhouse, Lever & Ashby Scraper runs on Apify, pay per result.

Run on Apify → Read the full actor page

Tips and pitfalls

FAQ

How can I tell if a company uses Workday?

Its job links point to a host ending in myworkdayjobs.com, such as adobe.wd5.myworkdayjobs.com. Pass that board URL to the actor to read the jobs with real posting dates.

Can the actor find a company's ATS from its domain alone?

Only for companies in the built-in index of 811 Greenhouse, Lever and Ashby employers. For anyone else, find the board URL on the careers page and pass it in; the actor does not guess company slugs.

Why scrape the ATS instead of a job board?

The ATS is the original source, so listings are fresher, include the employer's own departments and teams, and carry salary ranges where the employer publishes them in structured form.

Does it work for companies on SmartRecruiters?

No. SmartRecruiters and custom-built careers pages are not supported.

Actors used in this guide

Career Site Jobs — Workday, Greenhouse, Lever & Ashby Scraper

Scrape jobs straight from company career sites on Workday, Greenhouse, Lever, Ashby, Workable, Recruitee, Teamtailor, Personio and BambooHR. Search…

$3 per 1,000 · job result

Related guides

How to Get SEC Form D Startup Funding Data as a Daily Feed

Use Startup Funding Rounds to read EDGAR's daily Form D indexes and parse each filing into a row with issuer, amounts, industry and exemption.…

How to Get Local Business Leads Without Scraping Google Maps

Query the open Overture Maps places dataset by city and category with Business Places Data to get names, addresses, phones, websites and emails for…

All guides