# Company Jobs Scraper — Greenhouse, Lever, Ashby, Workday & More (`logical_vivacity/company-jobs-scraper`) Actor

Every open role a company is actually hiring for, straight from its own hiring system — Greenhouse, Lever, Ashby, Workday, Workable, SmartRecruiters and Recruitee. Paste a careers-page link; get normalised jobs with location, department, salary where shown, and apply links.

- **URL**: https://apify.com/logical\_vivacity/company-jobs-scraper.md
- **Developed by:** [Logical Vivacity](https://apify.com/logical_vivacity) (community)
- **Categories:** Jobs, Business, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.50 / 1,000 job founds

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?

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

## Company Jobs Scraper — Greenhouse, Lever, Ashby, Workday & More

**Every role a company is actually hiring for, from the company's own system.**

Job aggregators show you a copy of a posting, days late, sometimes after the role has closed. This Actor reads the hiring system the company actually runs — the one its own careers page is built on — so what you get is the live board: 655 open roles at one employer, 73 at another, in the same run and the same shape.

Paste a careers page URL. This Actor works out which platform it is and reads the whole board.

**You pay per job returned.** Boards that come back empty, unrecognised or unreachable cost nothing.

***

### Try it in 30 seconds

Put these in **Companies** and hit Start:

```
https://boards.greenhouse.io/stripe
https://jobs.lever.co/spotify
```

Two different hiring systems, no configuration, one table of jobs out.

***

### What you get per job

```jsonc
{
  "jobId": "5061534004",
  "title": "Senior Software Engineer, Payments",
  "company": "Stripe",
  "location": "San Francisco, CA",
  "department": "Engineering",
  "employmentType": "Full-time",
  "workplaceType": "Remote",
  "isRemote": true,

  "salary": "$180,000 – $240,000",      // where the company publishes it

  "postedAt": "2026-09-02T11:20:00+00:00",
  "postedDaysAgo": 15,

  "applyUrl": "https://boards.greenhouse.io/stripe/jobs/5061534004",
  "description": "About the team\nWe're looking for…",

  "source": "greenhouse",                // which hiring system it came from
  "status": "ok",
  "scrapedAt": "2026-09-17T19:04:11+00:00"
}
```

Export as JSON, CSV, Excel, XML or HTML, or pull it straight from the API.

***

### Hiring systems supported

| System | How you point at it |
|---|---|
| **Greenhouse** | The careers URL, or `greenhouse:company` |
| **Lever** | The careers URL, or `lever:company` |
| **Ashby** | The careers URL, or `ashby:company` |
| **Workday** | The careers URL (full boards are paginated to the end) |
| **Workable** | The careers URL, or `workable:company` |
| **SmartRecruiters** | The careers URL, or `smartrecruiters:company` |
| **Recruitee** | The careers URL, or `recruitee:company` |

You never have to say which one it is — paste the link and this Actor detects it. Mix all seven in a single run.

***

### Who uses this

**Recruiters and talent teams** — watch the boards of the companies you place into, see what's newly open, and know which teams are growing before the role hits the aggregators.

**Job boards and aggregators** — a clean, deduplicated feed straight from the source, with apply links that point at the real application, not a redirect chain. One schema across every platform, so your ingest pipeline is one pipeline.

**Sales teams selling to hiring companies** — open roles are the strongest buying signal there is. A company posting fifteen SDR jobs is a company buying sales tooling. Filter by title keyword and run it nightly.

**Market and talent researchers** — track headcount direction by team and location over time. Run the same company list weekly and the change is the dataset.

***

### What makes it different

**Straight from the company's own system.** No aggregator layer, so no stale rows, no reposted ghost jobs, and no listings that quietly disappeared a fortnight ago. If it's on the board, it's open.

**No login, no API key, no account.** Nothing to connect, nothing to authorise, nothing to keep alive.

**Seven platforms, one shape.** Greenhouse calls a team a department, Lever calls it a category, Workday doesn't name it at all. This Actor normalises every platform to the same field names, so `title`, `location`, `department`, `postedAt` and `applyUrl` mean the same thing whatever the source. Your spreadsheet doesn't care which ATS a company chose.

**Whole boards, not first pages.** Where a platform paginates, this Actor follows it to the end — a 2,000-role enterprise board comes back complete.

**Filters run before you're charged.** Title keywords, locations, remote-only and posting age are applied while reading, so a run that wants twelve engineering roles bills for twelve jobs, not the eight hundred on the board.

**Posting dates you can sort on.** Every platform expresses "when" differently — a timestamp, a date, "Posted 5 Days Ago". This Actor converts them all to an ISO timestamp plus a plain `postedDaysAgo` number.

***

### Settings that matter

| Setting | What it does |
|---|---|
| **Companies** | Careers page URLs, one per line — or the short `platform:company` form |
| **Job title contains** | Keep only titles containing one of these words |
| **Locations** | Keep only matching locations; partial text is fine |
| **Remote roles only** | Keep roles marked or described as remote |
| **Posted in the last N days** | Only recent openings — 7 or 14 for a "what's new" run |
| **Maximum jobs per company** | Cap per employer; 0 reads the whole board |
| **Include the full job description** | Off gives you a light, spreadsheet-friendly table |

Connection handling, pacing, retries and blocking are managed for you — there's nothing to configure and no proxy to set up.

### Automate it

```bash
curl -X POST "https://api.apify.com/v2/acts/YOUR_USERNAME~company-jobs-scraper/runs?token=YOUR_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{ "companies": [
          "https://boards.greenhouse.io/stripe",
          "https://jobs.lever.co/spotify",
          "ashby:ramp" ],
        "titleKeywords": ["engineer"],
        "remoteOnly": true,
        "postedWithinDays": 7,
        "includeDescription": false }'
```

Works with Make, Zapier, n8n, Google Sheets and the Apify API, and as an MCP tool for AI agents. Schedule it daily against a company list and you have a new-openings alert.

### Results you can trust

Every input reports what happened, so nothing fails silently:

| `status` | Meaning |
|---|---|
| `ok` | A job was returned and charged |
| `no_jobs` | The board was read fine, but nothing matched your filters — not charged |
| `unsupported` | We couldn't tell which hiring system this is — not charged |
| `error` | The board was briefly unreachable — retry that company; not charged |

***

### FAQ

**Do I need an account or API key for any of these platforms?**
No. This Actor reads the same public job boards a candidate sees.

**How do I find a company's board?**
Open their careers page and copy the URL from the address bar. If it's one of the seven supported systems, that's all you need.

**What if a company runs its careers page on something else?**
You get an `unsupported` row explaining what happened, and you aren't charged. Tell us which system and we'll look at adding it.

**Why is `salary` empty on some jobs?**
Because the company didn't publish one. This Actor returns what the board exposes and never guesses a range.

**Why is `description` empty on some jobs?**
A couple of platforms don't include the posting text in their board listing. The `applyUrl` always takes you to the full posting.

**Can I search across all companies on a platform without a list?**
No. This Actor reads the companies you name. It's built for watching a known list, not for crawling the whole internet.

**How fresh is it?**
It's read live at the moment of your run — that's the whole point. `scrapedAt` records exactly when.

**Can I track changes over time?**
Yes — run the same list on a schedule and diff on `jobId`. New IDs are new openings; missing IDs are roles that closed.

***

### Terms of Use

This Actor collects publicly available job postings that companies publish on their own careers pages. You are responsible for using the results lawfully and in line with applicable terms and regulations in your jurisdiction, including any marketing, employment and data-protection rules that apply to you. Postings are returned as the source published them and may be incomplete, outdated or changed after your run — verify before acting on a result. This Actor is provided "as is", without warranty of accuracy or fitness for a particular purpose, and is not affiliated with, endorsed by, or sponsored by Greenhouse, Lever, Ashby, Workday, Workable, SmartRecruiters, Recruitee or any other applicant tracking vendor, nor by any employer whose board you read.

***

*Need a hiring system we don't cover yet?* Open an issue on the Actor's Issues tab with the careers page URL.

# Actor input Schema

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

One per line. Paste the careers page URL and Roster works out which hiring system it runs on. You can also write it short as platform:company — for example greenhouse:stripe, lever:spotify, ashby:ramp, workable:acme, smartrecruiters:bosch or recruitee:acme.

## `titleKeywords` (type: `array`):

Keep only jobs whose title contains one of these words. Leave empty for every open role.

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

Keep only jobs whose location matches one of these. Partial text is fine — "London", "Germany", "NY".

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

Keep only jobs the company has marked, or described, as remote.

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

Keep only jobs posted recently. 0 means no limit. Use 7 or 14 to catch new openings on a schedule.

## `maxJobsPerCompany` (type: `integer`):

Caps how many jobs are returned for each company. 0 means the whole board — some large employers have thousands.

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

Adds the posting text to every job. Turn it off for a lighter dataset you can open in a spreadsheet.

## Actor input object example

```json
{
  "companies": [
    "https://boards.greenhouse.io/stripe",
    "https://jobs.lever.co/spotify"
  ],
  "titleKeywords": [
    "engineer",
    "designer"
  ],
  "remoteOnly": false,
  "postedWithinDays": 0,
  "maxJobsPerCompany": 0,
  "includeDescription": true
}
```

# Actor output Schema

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

Every job with title, location, department, salary where shown, and its apply link.

## `overview` (type: `string`):

The same rows as a spreadsheet-style table, with the most useful columns first.

# 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": [
        "https://boards.greenhouse.io/stripe",
        "https://jobs.lever.co/spotify"
    ],
    "titleKeywords": [
        "engineer",
        "designer"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("logical_vivacity/company-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": [
        "https://boards.greenhouse.io/stripe",
        "https://jobs.lever.co/spotify",
    ],
    "titleKeywords": [
        "engineer",
        "designer",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("logical_vivacity/company-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": [
    "https://boards.greenhouse.io/stripe",
    "https://jobs.lever.co/spotify"
  ],
  "titleKeywords": [
    "engineer",
    "designer"
  ]
}' |
apify call logical_vivacity/company-jobs-scraper --silent --output-dataset

```

## MCP server setup

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