# Jobs Search API – Search Career Sites by Job Title & Country (`pharaoh_data/jobs-search-api`) Actor

Search jobs by title, country, and keyword across the career sites of hundreds of companies on Workday, Greenhouse, Lever, Ashby, and Workable. Live data straight from each employer's board, with new and closed job alerts.

- **URL**: https://apify.com/pharaoh_data/jobs-search-api.md
- **Developed by:** [Pharaoh Data](https://apify.com/pharaoh_data) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

## Jobs Search API – Search Career Sites by Job Title & Country

### Search jobs straight from employers' own career sites

Type a job title and a country. This Actor searches the career sites of **650 companies** on **Workday, Greenhouse, Lever, Ashby, and Workable** and returns every matching job with **title, locations, ISO country codes, department, salary when published, posting date, apply link, and full description**.

The jobs come live from each employer's own board at the moment you run it. Nothing is a stale copy of a job site, and nothing is reposted by an agency. Save a search as a scheduled task and each run tells you which jobs are **new, updated, or closed**.

**Built for:**

- **Job boards and newsletters**: fill a niche board ("ML jobs in the UAE", "remote data jobs in Europe") with fresh roles direct from employers.
- **Recruiters and sourcers**: see who is hiring for the role you recruit for, by country, every morning.
- **Sales and partnerships teams**: hiring for a role is a buying signal. Find companies hiring data engineers in Saudi Arabia and reach them first.
- **Researchers and analysts**: measure demand for a skill or a role across hundreds of employers.

### How it works

1. **A built-in index of 665 company job boards** from 651 companies (refreshed on 2026-10-18, with about 149,000 jobs at the time; 91 of the boards hire in the Gulf) records which countries each board hires in and which words its job titles use.
2. Your search picks only the boards that can match: for example, boards with jobs in the UAE whose titles contain "data" and "engineer". They're ranked by how many jobs they have in your countries.
3. Those boards are read **live**, and every job is checked against your filters. Workday sites are searched with their own search box, so only matching jobs are downloaded.

|                                 |                                                                                                                                                                                                                                            |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Direct from employers**       | Every job links to the employer's own posting and apply page. No aggregator duplicates, no agency reposts.                                                                                                                                 |
| **Countries that are right**    | You can enter `Germany`, `AE`, or `"Saudi Arabia"`. Locations are read as countries even when they only name a state, a city, or a code: "San Francisco, CA" is US, "Vancouver, CA" is Canada, and "Dubai" and "Remote - US" are read too. |
| **One schema for five systems** | Workday, Greenhouse, Lever, Ashby, and Workable jobs share one record shape and a stable `jobId`.                                                                                                                                          |
| **Alerts built in**             | With change tracking on, each run labels jobs new, updated, or unchanged, and reports jobs that disappeared as closed. "Changes only" mode saves just the changes.                                                                         |
| **Add your own boards**         | Paste any Greenhouse, Lever, Ashby, Workable, or Workday board URL to search it alongside the index.                                                                                                                                       |
| **Polite and compliant**        | Public job-board endpoints only, with no logins and no proxies. robots.txt is checked for every host, and requests to each host are rate-limited. Contact details in descriptions are redacted by default.                                 |

### Quick start

```json
{
    "jobTitles": ["data engineer", "machine learning engineer"],
    "countries": ["United Arab Emirates", "Saudi Arabia"],
    "keywords": [],
    "postedWithinDays": 30,
    "maxBoards": 100,
    "maxResults": 1000,
    "trackChanges": true,
    "outputMode": "all"
}
```

- **Job titles** match when the title contains the phrase ("data engineer" matches "Senior Data Engineer, Payments"). Several phrases are combined with OR.
- **Countries, Locations, Keywords, and Posted within days** narrow the results further.
- **Only these companies / Exclude companies** limit the search to, or leave out, companies in the index.
- **Extra job board URLs** add boards that aren't in the index.
- For alerts, save the input as a task, schedule it (for example daily), and set **Output** to **Changes only**.

### Output

Each dataset item is one job:

```json
{
    "jobId": "ashby:example:1f0c9a52-6d1e-4b8e-9c55-0a2b3c4d5e01",
    "company": "Example",
    "provider": "ashby",
    "boardUrl": "https://jobs.ashbyhq.com/example",
    "title": "Senior Data Engineer",
    "location": "Dubai",
    "locations": ["Dubai"],
    "country": "AE",
    "countryName": "United Arab Emirates",
    "countries": ["AE"],
    "workplaceType": "hybrid",
    "department": "Engineering / Data Platform",
    "employmentType": "Full-time",
    "salary": "AED 30K - 40K",
    "salaryRange": { "min": 30000, "max": 40000, "currency": "AED", "interval": "month" },
    "postedAt": "2026-10-12T09:15:00.000Z",
    "jobUrl": "https://jobs.ashbyhq.com/example/1f0c9a52-6d1e-4b8e-9c55-0a2b3c4d5e01",
    "applyUrl": "https://jobs.ashbyhq.com/example/1f0c9a52-6d1e-4b8e-9c55-0a2b3c4d5e01/application",
    "description": "Build our data platform. …",
    "scrapedAt": "2026-10-18T09:00:00.000Z",
    "changeType": "new",
    "changedFields": [],
    "firstSeenAt": "2026-10-18T09:00:00.000Z",
    "lastSeenAt": "2026-10-18T09:00:00.000Z",
    "closedAt": null
}
```

`RUN_SUMMARY` in the default key-value store shows the index date and size, how many boards could match and how many were searched, the totals, and every board with matches, closures, or errors.

### Use it from code, n8n, Make, or an AI agent

```bash
curl -X POST "https://api.apify.com/v2/acts/pharaoh_data~jobs-search-api/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"jobTitles":["product manager"],"countries":["DE","NL"],"postedWithinDays":14,"maxResults":200}'
```

```python
import os

from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("pharaoh_data/jobs-search-api").call(run_input={
    "jobTitles": ["data engineer"],
    "countries": ["AE", "SA"],
    "outputMode": "changes",
})
for job in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(job["changeType"], job["company"], job["title"], job["jobUrl"])
```

- **Alerts:** schedule a task, then add a webhook or the Slack, email, or Google Sheets integration on "Run succeeded".
- **AI agents (MCP):** `https://mcp.apify.com/?actors=pharaoh_data/jobs-search-api`

### Limits and good to know

- **It searches the companies in the index**, not the whole web. The index favours technology, fintech, AI, and large employers, and includes Gulf and MENA companies where their boards are on these five systems. To search other companies, add their board URLs, or use [Career Site Jobs by Company Name](https://apify.com/pharaoh_data/career-site-jobs-finder) to find boards from company names.
- **The index is refreshed periodically.** A board that started hiring in a new country, or for a new kind of title, after the last refresh may be skipped for that search. The jobs themselves are always read live.
- **Company names come from the boards.** Two companies with the same name can both appear, for example "Circle". Use **Exclude companies** or **Job board systems** to narrow a search.
- **`maxBoards`** limits how many boards are searched, most promising first. The run log and `RUN_SUMMARY` say how many more could match.
- **Workday returns at most 2,000 jobs per search**, and descriptions need one request per job. "Changes only" mode reads descriptions only for new and updated jobs.
- Use the data in line with each employer's terms and applicable law. Descriptions are employer content; contact details in them are redacted by default.

### Pricing

Pay per event: you pay per **saved job record** (including closed-job records), plus Apify's small Actor start event. Boards searched without matches and jobs that don't match your filters are free. If the Pricing tab lists a **Job change** event, records saved in "Changes only" mode are billed at that price. See the **Pricing** tab for current amounts.

### FAQ

**Why did my search return fewer jobs than a job site shows?**
This Actor returns only jobs posted on the employers' own boards for the companies in its index, which removes duplicates and agency reposts. Raise **Maximum boards to search**, remove filters, or add board URLs to widen it.

**Can I search one company?**
Yes. Put its name in **Only these companies**. If it isn't in the index, paste its board URL under **Extra job board URLs**.

**What counts as a closed job?**
A job this search saved in an earlier run that is no longer listed on a board that was read in full. On Workday sites it can also mean the job no longer matches your title search.

# Actor input Schema

## `jobTitles` (type: `array`):

Phrases to find in job titles, such as "data engineer" or "account executive". A job matches if its title contains any of them.

## `countries` (type: `array`):

Keep jobs in these countries (names or ISO codes, such as US, Germany, "United Arab Emirates"). Leave empty for all.

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

Optional city or region terms, such as London, Remote, or Dubai.

## `keywords` (type: `array`):

Optional terms to find in the title, description, department, or location, such as Python or fintech.

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

Keep jobs posted within this many days. 0 disables the filter.

## `providers` (type: `array`):

Search only boards on these systems. Leave empty for all five.

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

Optional: search only these companies from the index, such as Stripe or Careem. To search a company that isn't in the index, add its board URL below.

## `excludeCompanies` (type: `array`):

Optional: companies to leave out, such as your own employer or current clients.

## `additionalBoardUrls` (type: `array`):

Optional Greenhouse, Lever, Ashby, Workable, or Workday board URLs to search as well, such as https://jobs.lever.co/palantir.

## `maxBoards` (type: `integer`):

Boards that can match are searched in order of how many jobs they have in your countries (or overall). More boards find more jobs and take longer.

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

Maximum matching jobs saved from each board.

## `maxResults` (type: `integer`):

Maximum job records saved per run, including closed-job records. Each record is one billable result.

## `includeDescriptions` (type: `boolean`):

Include plain-text descriptions. Workday descriptions need one extra request per job.

## `trackChanges` (type: `boolean`):

Label jobs new, updated, or unchanged compared with the previous run of the same search, and report jobs that disappeared as closed. History is kept in your account's named key-value store jobs-search-api-state.

## `outputMode` (type: `string`):

"All matching jobs" saves every match. "Changes only" saves new, updated, and closed jobs, for alerts.

## `includeClosed` (type: `boolean`):

Save a record with changeType "closed" when a previously saved job is no longer listed on a fully read board.

## `monitorId` (type: `string`):

Optional name for this search's history. When empty, it is derived from the search settings.

## `redactContactDetails` (type: `boolean`):

Remove email addresses, phone numbers, and personal LinkedIn links from descriptions.

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

How many boards to read at once (1–8). Requests to each host stay rate-limited.

## Actor input object example

```json
{
  "jobTitles": [
    "software engineer",
    "data engineer",
    "product manager"
  ],
  "countries": [
    "United Kingdom",
    "United Arab Emirates"
  ],
  "locations": [],
  "keywords": [],
  "postedWithinDays": 0,
  "providers": [],
  "companies": [],
  "excludeCompanies": [],
  "additionalBoardUrls": [],
  "maxBoards": 100,
  "maxJobsPerCompany": 200,
  "maxResults": 100,
  "includeDescriptions": true,
  "trackChanges": true,
  "outputMode": "all",
  "includeClosed": true,
  "monitorId": "",
  "redactContactDetails": true,
  "maxConcurrency": 4
}
```

# Actor output Schema

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

Dataset of job records with change status.

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

Boards searched, matching boards in the index, and per-board totals: matching, saved, new, updated, closed, by country.

# 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 = {
    "jobTitles": [
        "software engineer",
        "data engineer",
        "product manager"
    ],
    "countries": [
        "United Kingdom",
        "United Arab Emirates"
    ],
    "maxResults": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("pharaoh_data/jobs-search-api").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 = {
    "jobTitles": [
        "software engineer",
        "data engineer",
        "product manager",
    ],
    "countries": [
        "United Kingdom",
        "United Arab Emirates",
    ],
    "maxResults": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("pharaoh_data/jobs-search-api").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 '{
  "jobTitles": [
    "software engineer",
    "data engineer",
    "product manager"
  ],
  "countries": [
    "United Kingdom",
    "United Arab Emirates"
  ],
  "maxResults": 100
}' |
apify call pharaoh_data/jobs-search-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,pharaoh_data/jobs-search-api"
        }
    }
}
```

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/YL0HtU9SVZLx2JlwD/builds/IRKk6vPFGkAxNHolT/openapi.json
