# Company Careers Job Scraper (`jobscrawler/company-careers-job-scraper`) Actor

Extract open roles from company career pages with job title, location, department, seniority clues, source URL, and hiring-intent lead signals.

- **URL**: https://apify.com/jobscrawler/company-careers-job-scraper.md
- **Developed by:** [Jobs Scraper](https://apify.com/jobscrawler) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.99 / 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.

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

### What does Company Careers Job Scraper do?

Extract **real published company vacancies** from public [Greenhouse](https://docs.greenhouse.io/job-board.html) and [Lever](https://github.com/lever/postings-api) GET APIs, or individual JobPosting JSON-LD on a supplied public company career page. It returns full published job-description text, not navigation anchors, generic page descriptions, or search-engine snippets. No paid vendor key, login, application submission or private applicant data is used.

### Why use company career data?

Monitor actual hiring activity, compare role requirements, discover source-declared departments and locations, and maintain links to current individual postings. Apify can schedule runs, expose the dataset through its API, and connect exports to existing workflows. A published vacancy is a hiring signal, not proof of company growth or a guarantee that applications remain open indefinitely.

The default input reads Discord's currently published Greenhouse board and saves up to ten jobs. That company is used only for an empty input. Explicit company URLs never fall back to Discord or an unrelated data provider.

### What data can it extract?

| Field | Type | Meaning |
| --- | --- | --- |
| jobId, title, jobUrl | string | Actual source identity, job title and individual posting URL |
| description | string | Full published description text, including native description sections |
| companyName | string | Explicit source employer name; omitted when unavailable |
| location, locations, country | string/array | Source-declared locations, not inferred geography |
| departments, offices | array | Published teams, departments and offices |
| jobType, workplaceType | string | Explicit source employment/workplace labels |
| salary, salaryRange | string/object | Original pay disclosure, currency and pay period when supplied |
| postedAt, updatedAt, validThrough | string | Separate native timestamps; never replaced by scrape time |
| skills, qualifications, responsibilities | array/string | Explicit JobPosting properties |
| seniorityClues | array | Clearly derived exact title tokens, not verified seniority |
| hiringSignal | string | Derived published_vacancy label based on an actual source posting |
| sourcePortal, sourceUrl, boardKey | string | Provenance and exact extraction route |

Unavailable values, empty arrays/objects and blank strings are omitted recursively; genuine source zero and false are preserved. Native pay periods and currencies are never guessed, converted or annualized. Public Greenhouse custom metadata may be included, but application forms, consent questions, applicant accounts and private user metadata are not collected.

### How to scrape company career pages

1. Leave the input empty for the verified default or supply startUrl/startUrls.
2. Set maxItems, optionally searchQuery, location, department or publishedAfter.
3. Start the Actor and inspect the dataset and separate source evidence.
4. Download the dataset in various formats such as JSON, HTML, CSV, or Excel.

Recognized native URLs include Greenhouse board/posting URLs and Lever US/EU board/posting URLs, including their exact public API equivalents. Other public HTTPS pages are inspected for genuine JobPosting JSON-LD. Up to maxPages related same-host career links or recognized native board links may be followed, with discovery depth limited to one. Arbitrary script execution, hidden browser state, account logins, anti-bot bypasses and unrelated-source substitutions are not supported. A European Greenhouse board currently fails explicitly rather than silently querying the US API.

### Input

See the input tab for full configuration options. startUrl overrides startUrls. searchQuery overrides legacy keyword only when nonempty. All query/location/department/date filtering is local to real source records; this is not a web-wide company discovery engine.

Example native board input:

```json
{"startUrl":"https://job-boards.greenhouse.io/discord","maxItems":10}
```

Example custom-page input (replace with a real authorized company URL):

```json
{"startUrls":[{"url":"https://example.org/careers"}],"searchQuery":"engineer","maxItems":10,"maxPages":5}
```

publishedAfter uses an actual YYYY-MM-DD calendar date and requires a source posting date; jobs without one cannot satisfy it. maxItems is a global cap across all companies. Independent company sources run in bounded groups controlled by maxConcurrency, then merge in caller order. Requests on each origin are serialized and obey its robots crawl delay. Greenhouse full descriptions arrive in one batched native API response. Lever uses bounded native pagination. maxRequests includes robots and redirects, and each request has a timeout.

### Output

The following two abbreviated objects are anonymized documentation examples, not live test output:

```json
[
  {
    "jobId":"1234567890",
    "title":"Senior Software Engineer",
    "companyName":"Example Company",
    "description":"Example full role responsibilities and qualifications.",
    "jobUrl":"https://job-boards.greenhouse.io/example/jobs/1234567890",
    "sourcePortal":"greenhouse",
    "dataMode":"live_public_api",
    "seniorityClues":["senior"],
    "hiringSignal":"published_vacancy"
  },
  {
    "jobId":"00000000-0000-4000-8000-000000000001",
    "title":"Research Engineer",
    "description":"Example published introduction, requirements and benefits.",
    "jobUrl":"https://jobs.lever.co/example/00000000-0000-4000-8000-000000000001",
    "sourcePortal":"lever",
    "dataMode":"live_public_api",
    "hiringSignal":"published_vacancy"
  }
]
```

SOURCE_METADATA contains bounded HTTP outcomes, native page counts and missing-detail skips. RUN_SUMMARY records result counts and timestamps; ERROR_DIAGNOSTIC contains a sanitized failure. Diagnostics never become job rows. A zero-match or access-denied run fails explicitly; it does not invent records or claim success. Some sources genuinely contain fewer than ten matching vacancies.

### How much will it cost?

Check the Actor's current pricing tab for any Store charges and Apify platform usage. This source code neither sets marketplace prices nor promises a fixed cost or response time. There is no paid source API subscription in this implementation, and proxy configuration does not silently enable paid proxy traffic.

### FAQ, responsible use and support

Use public source data only where you have a legitimate purpose and necessary permission. Source content is untrusted, parsed without execution, and cleaned as text. Robots exclusions, access denials and rate limits stop retrieval without rotating identities, cookies, hosts or proxies. HTTPS domains are validated and private/IP-literal destinations rejected; no credentials are forwarded to company websites.

Why fewer records? Filters, source inventory, missing full descriptions, request budgets and already-expired JSON-LD postings can reduce results. Broaden the actual query or provide the correct native board URL rather than substituting unrelated data. Arbitrary career systems without JobPosting JSON-LD or a supported native public API are not guaranteed to work. Open an issue with a public URL and sanitized error—never API keys or applicant data. Use the API tab for programmatic access.

# Actor input Schema

## `startUrl` (type: `string`):

One public HTTPS company career page or native board/posting URL. Overrides startUrls.

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

Up to ten public HTTPS pages. Empty uses the verified Discord Greenhouse board. Explicit URLs are never replaced by unrelated boards.

## `searchQuery` (type: `string`):

Case-insensitive substring in the native title or full description. Local filter, not search-engine results.

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

Used only when searchQuery is empty.

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

Case-insensitive match against published job location labels.

## `department` (type: `string`):

Case-insensitive match against published department or team labels.

## `publishedAfter` (type: `string`):

Optional real YYYY-MM-DD date. Jobs lacking a source publication date do not pass this filter.

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

Global output cap, not per URL.

## `maxConcurrency` (type: `integer`):

Independent company sources run in bounded groups; per-host requests are serialized and respect robots crawl delay.

## `maxPages` (type: `integer`):

Lever API pages per board, or discovered career pages, bounded to depth one. Greenhouse returns its complete board in one response.

## `pageSize` (type: `integer`):

Lever public API page size.

## `maxRequests` (type: `integer`):

Global cap including robots, redirects, board and page requests.

## `requestTimeoutSecs` (type: `integer`):

Each source request is time-bounded. Denials and rate limits are not retried.

## Actor input object example

```json
{
  "startUrl": "https://job-boards.greenhouse.io/discord",
  "startUrls": [
    {
      "url": "https://job-boards.greenhouse.io/discord"
    }
  ],
  "searchQuery": "software engineer",
  "keyword": "software engineer",
  "location": "",
  "department": "",
  "publishedAfter": "",
  "maxItems": 10,
  "maxConcurrency": 3,
  "maxPages": 3,
  "pageSize": 20,
  "maxRequests": 30,
  "requestTimeoutSecs": 25
}
```

# Actor output Schema

## `dataset` (type: `string`):

Live individual job records.

## `runSummary` (type: `string`):

Real result counts and status.

## `diagnostics` (type: `string`):

Request outcomes and sanitized failures.

# 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 = {
    "startUrl": "https://job-boards.greenhouse.io/discord",
    "startUrls": [
        {
            "url": "https://job-boards.greenhouse.io/discord"
        }
    ],
    "searchQuery": "software engineer",
    "keyword": "software engineer"
};

// Run the Actor and wait for it to finish
const run = await client.actor("jobscrawler/company-careers-job-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 = {
    "startUrl": "https://job-boards.greenhouse.io/discord",
    "startUrls": [{ "url": "https://job-boards.greenhouse.io/discord" }],
    "searchQuery": "software engineer",
    "keyword": "software engineer",
}

# Run the Actor and wait for it to finish
run = client.actor("jobscrawler/company-careers-job-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 '{
  "startUrl": "https://job-boards.greenhouse.io/discord",
  "startUrls": [
    {
      "url": "https://job-boards.greenhouse.io/discord"
    }
  ],
  "searchQuery": "software engineer",
  "keyword": "software engineer"
}' |
apify call jobscrawler/company-careers-job-scraper --silent --output-dataset

```

## MCP server setup

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