# SimplyHired Job Scraper | Contacts, Salary & 27 Markets (`corvuslab/simplyhired-scraper`) Actor

Scrape SimplyHired jobs across 27 country markets. Extract contacts (emails, phones, socials), structured salary, skills, and qualifications. Incremental monitoring with Telegram/Slack/Discord alerts.

- **URL**: https://apify.com/corvuslab/simplyhired-scraper.md
- **Developed by:** [Corvuslab](https://apify.com/corvuslab) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.99 / 1,000 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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

### What does SimplyHired Job Scraper do?

SimplyHired Job Scraper extracts structured job listings from SimplyHired across **27 international markets** — from the US and UK to Brazil, Japan, South Africa and more. Each record includes **contact details** (emails, phones, URLs, social profiles) extracted from the description, **structured salary data** (min, max, period, currency), skills, qualifications, benefits, requirements, geo coordinates, and the full description in text, HTML or Markdown. No code needed — configure it in the visual editor and export to JSON, CSV, Excel, or pull results via the API or an MCP tool for AI agents.

Give it a search keyword and optional location, pick a country market, and it returns every matching job as a clean, typed record. For each listing you get the core fields (title, company, salary, location, type, date). Turn on **Fetch full details** to also pull the complete description, structured salary, contacts, skills, geo coordinates, qualifications, benefits and requirements arrays. Use the **Require contact** filter to keep only listings with an email or phone — instant lead-gen. You can also paste SimplyHired search or job URLs directly instead of a keyword search.

> New to Apify? You can sign up for free and use the included monthly platform credit to try this Actor.

**Why this scraper**

- ⚡ **Fast & low-cost** — lightweight requests with no browser overhead, so large runs stay cheap.
- 🧾 **Rich, typed records** — 40+ structured fields per job, not raw HTML.
- ♻️ **Cheap to monitor** — incremental mode re-scrapes only what changed (see below).
- 🔔 **Notifications built in** — Telegram, Slack, Discord or any webhook.
- 🤖 **AI- & API-ready** — compact output, MCP-friendly, one-click integrations.

***

### Key features

- 🌍 **27 international markets** — search jobs across the US, UK, Canada, Australia, India, Germany, France, Spain, Italy, Netherlands, Brazil, Mexico, Argentina, Japan, South Korea, China, Sweden, Ireland, Austria, Switzerland, Portugal, South Africa, Belgium and regional variants (Canadian French, Belgian French, Swiss French/Italian).
- 💰 **Structured salary data** — parsed into min, max, period (hourly/daily/weekly/monthly/yearly) and ISO currency code, ready for analysis without regex.
- 📍 **Geo coordinates** — latitude and longitude for every job, enabling radius searches and map visualizations in your own tools.
- 🔎 **Search or URL scraping** — run a keyword + location search, or paste SimplyHired search and detail URLs for targeted extraction.
- 🎚️ **Rich post-scrape filters** — job type (full-time, part-time, contract, internship and more), remote/hybrid, posted-within-N-days, and minimum salary — applied automatically so you export only what matters.
- 🧠 **Full details** — qualifications, requirements, benefits arrays and the complete job description in text, HTML and Markdown.
- 📇 **Contact extraction** — emails, phone numbers, URLs and social profiles pulled from each listing, with a `requireContact` filter for instant lead-gen.
- ♻️ **Incremental monitoring** — schedule it and get only what changed (NEW / UPDATED / EXPIRED); unchanged jobs are skipped before their page is even fetched.
- 🔔 **Notifications** — Telegram, Slack, Discord or any webhook (n8n / Make / Zapier).
- 🤖 **AI-ready** — compact + drop-empty output modes keep payloads small for LLMs and MCP.

***

### 🚀 How to scrape SimplyHired

1. Open the actor and enter a **search keyword** (e.g. `data scientist`) and/or a **location** (e.g. `London`) — or paste a SimplyHired search URL.
2. Pick a **country market** (defaults to US) and set **Max results**.
3. Choose whether to **fetch full details** and apply any **filters** (job type, remote, recency, minimum salary).
4. (Optional) Turn on **incremental mode** and a **notification** channel, then **Schedule** it.
5. Click **Start**.
6. Download the data as **JSON, CSV or Excel**, or pull it from the **API**.

New to Apify? Create a free account — it comes with monthly credit, no credit card required.

***

### Input

Configure it in the visual editor — no code needed — or pass JSON via the API.

| Field | What it does |
|---|---|
| `query` | Keyword search (comma-separate for multiple searches). |
| `location` | City, state, zip code or "Remote". |
| `market` | Country site to search — 27 markets from US to Japan to South Africa. |
| `startUrls` | Scrape specific SimplyHired search or job detail URLs (market auto-detected). |
| `jobType` | Filter by employment type: full-time, part-time, contract, temporary, internship, etc. |
| `workLocation` | Filter to remote or hybrid jobs only. |
| `datePosted` | Keep only jobs posted within the last N days. |
| `minimumSalary` | Keep only jobs at or above a salary threshold (annual, local currency). |
| `includeDetails` | Fetch each job's page for the full description, structured salary, coordinates and more. |
| `requireContact` | Keep only listings with an email, phone or both — built-in lead-gen filter. |
| `compact` | Return only core fields — ideal for AI agents and MCP clients. |
| `incrementalMode` | Emit only what changed since the last run. |
| `maxResults` | Cap the number of records (0 = unlimited). |

...and **28 inputs** in total — the table shows the essentials; the rest cover notification channels, output/AI modes and advanced tuning, all in the visual editor.

#### Example inputs

**Basic keyword search**

```json
{ "query": "software engineer", "location": "New York, NY", "maxResults": 100 }
```

**Multi-market search with filters**

```json
{
  "query": "data scientist",
  "market": "GB",
  "jobType": ["Full-time", "Contract"],
  "workLocation": ["remote"],
  "datePosted": 7,
  "maxResults": 200
}
```

**Incremental monitoring with notifications**

```json
{
  "query": "product manager",
  "market": "DE",
  "incrementalMode": true,
  "telegramToken": "<YOUR_BOT_TOKEN>",
  "telegramChatId": "<YOUR_CHAT_ID>",
  "maxResults": 0
}
```

***

### Output

Each item in the dataset is one job listing. Every record includes the core fields; enabling **Fetch full details** (on by default) adds the complete description, structured salary breakdown, geo coordinates, qualifications, benefits and requirements. Here is a real example record:

```json
{
  "id": "f3eTbZq8bFmVJoalGbb2PfvIaww0P7gkjiqkxzPzgEN3oWfS59L5YA",
  "title": "Backend Engineer",
  "url": "https://www.simplyhired.com/job/f3eTbZq8bFmVJoalGbb2PfvIaww0P7gkjiqkxzPzgEN3oWfS59L5YA",
  "company": "Bevel",
  "companyRating": null,
  "companyUrl": "https://www.simplyhired.com/browse-jobs/companies/Bevel",
  "location": "New York, NY",
  "city": "New York",
  "state": "NY",
  "latitude": 40.71427,
  "longitude": -74.00597,
  "salary": "$150,000 - $190,000 a year",
  "salaryMin": 150000.0,
  "salaryMax": 190000.0,
  "salaryPeriod": "year",
  "salaryCurrency": "USD",
  "employmentType": ["Full-time"],
  "remoteAttributes": [],
  "requirements": ["Mid-level", "Math", "AI", "2 years", "Python"],
  "skills": ["ML ops", "Model versioning", "Scalability", "Backend development", "Health data processing"],
  "qualifications": ["Statistics", "Math", "Scalability", "Developing and maintaining backend systems"],
  "benefits": ["Commuter assistance", "Health insurance", "Dental insurance", "401(k)", "Vision insurance"],
  "snippet": "Continuously iterate on the engineering process and culture...",
  "datePosted": "2026-03-04T19:16:30.814000+00:00",
  "datePublished": "2026-01-14T06:00:00+00:00",
  "isSponsored": false,
  "isExpired": false,
  "source": "simplyhired.com",
  "sourceSearchUrl": "https://www.simplyhired.com/search?q=software%20engineer&l=New%20York%2C%20NY",
  "searchKeyword": "software engineer",
  "scrapedAt": "2026-08-28T08:48:37.192947+00:00",
  "detailFetched": true,
  "contentHash": "e109a7e7256021056e91ad1322461212f066161f"
}
```

Each record can also include `description`, `descriptionHtml` and `descriptionMarkdown` — choose the format with the **Description format** input. When incremental mode is on, records carry a `changeType` field (NEW / UPDATED / EXPIRED) and repost detection fields (`isRepost`, `repostOfId`, `repostDetectedAt`).

#### Data fields

- **Core** — id, title, url, company, location, salary, employmentType, datePosted, snippet, source.
- **Structured salary** — salaryMin, salaryMax, salaryPeriod, salaryCurrency — parsed and typed, ready for analysis.
- **Geo** — city, state, latitude, longitude.
- **Details** (with `includeDetails`) — description, descriptionHtml, descriptionMarkdown, requirements, skills, qualifications, benefits, remoteAttributes.
- **Company** — companyUrl, companyLogo, companyRating.
- **Contacts & signals** — extractedEmails, extractedPhones, extractedUrls, socialProfiles.
- **Posting metadata** — datePublished, isExpired, expirationDate, isSponsored, isIndeedApply.
- **Provenance** — sourceSearchUrl, searchKeyword, scrapedAt, detailFetched.
- **Incremental** — changeType, isRepost, repostOfId, repostDetectedAt, contentHash.

Every field is present in standard mode (missing values are `null`); **compact mode** returns the core fields only, for lean AI/MCP payloads. With **`excludeEmptyFields`** enabled, null/empty fields are omitted entirely.

***

### 💡 What can you do with SimplyHired data?

- **Lead generation** — filter jobs that mention contact details and feed them straight into your outreach pipeline with `requireContact`.
- **Salary benchmarking** — structured min/max/period/currency fields across 27 markets let you compare compensation without scrubbing free text.
- **Global labor-market research** — track hiring trends, job-type distribution and demand signals across countries and industries.
- **Job monitoring & alerts** — schedule incremental runs with Telegram or Slack notifications to catch new openings the moment they appear.
- **Enrichment & aggregation** — feed clean, typed job records into your own app, data warehouse or spreadsheet.
- **AI agents & pipelines** — compact output plugs straight into LLM/MCP workflows for automated analysis.

***

### ♻️ Incremental monitoring — pay for changes, not repeats

Schedule the actor and turn on **incremental mode**: each run compares against the last and emits only **NEW / UPDATED / EXPIRED** records — unchanged jobs are skipped *before* their detail page is fetched, so a daily watch costs a fraction of a full re-scrape.

| Daily churn | of 1,000 tracked | billable records | cost per run | you save |
|---|---|---|---|---|
| 5 % | 1,000 | 50 | ~$0.05 + start | **95 %** |
| 15 % | 1,000 | 150 | ~$0.15 + start | **85 %** |
| 30 % | 1,000 | 300 | ~$0.30 + start | **70 %** |

The first run seeds the baseline and bills in full; every run after that bills only the delta. Built-in repost detection (`isRepost`, `repostOfId`) catches recycled listings so you never double-count them.

***

### 💰 How much does it cost to scrape SimplyHired?

This Actor uses the **pay-per-event** pricing model — you pay only for what you use, with no browser or proxy overhead.

| Event | Price |
|---|---|
| Actor start | **$0.0005** per run |
| Result | **$0.99 per 1,000 results** ($0.00099 each) |

**Example costs**

| Use case | Records | Cost |
|---|---|---|
| Quick search (50 jobs) | 50 | ~$0.05 |
| Full market scan (1,000 jobs) | 1,000 | ~$0.99 |
| Daily incremental watch (5 % churn of 1,000) | 50/day | ~$0.05/day ≈ $1.50/month |
| Large multi-market export (10,000 jobs) | 10,000 | ~$9.90 |

No proxy required — the scraper uses lightweight HTTP requests with TLS impersonation, so there are no hidden proxy costs on top of the prices above.

***

### 🔌 Integrations & export

Export to **JSON, CSV, Excel** or an HTML table, or pull from the **REST API** and the **JavaScript / Python** clients. Runs on a **schedule**, connects to **Google Sheets, Slack, Make, Zapier and n8n**, and works as an **MCP tool** for AI agents — compact mode keeps token usage small.

***

### 🔗 Using the API

You can run this Actor from your own code. Example with the Apify Python client:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")

run_input = {
    "query": "data scientist",
    "market": "GB",
    "maxResults": 50,
}

run = client.actor("corvuslab/simplyhired-scraper").call(run_input=run_input)

print("Results: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

The Actor also works with the JavaScript/TypeScript client, the Apify CLI and the REST API.

***

### ❓ FAQ

**Do I need a proxy or login?** No — it runs out of the box with no credentials required. Apify Proxy is available under Advanced for high-volume runs.

**Which countries are supported?** 27 markets: US, UK, Canada, Australia, India, Germany, France, Spain, Italy, Netherlands, Brazil, Mexico, Argentina, Japan, South Korea, China, Sweden, Ireland, Austria, Switzerland, Portugal, South Africa, Belgium, plus regional variants (Canadian French, Belgian French, Swiss French, Swiss Italian).

**Can I get only new jobs on a schedule?** Yes — turn on incremental mode and schedule it; each run emits only what changed and can notify your Telegram, Slack, Discord or webhook channel.

**What formats can I export?** JSON, CSV, Excel, HTML table, or via the API.

**Is it good for AI agents?** Yes — enable compact mode; the output is MCP-friendly and keeps token usage small.

**How many records can I get?** As many as the search returns — set `maxResults` to 0 for unlimited.

**Can it notify me when new jobs appear?** Yes — add a Telegram, Slack, Discord or generic webhook target under Notifications, and combine with incremental mode so you only get pinged about new and updated listings.

**Is scraping SimplyHired legal?** This actor collects only **publicly available** data on SimplyHired. You are responsible for how you use the extracted data — in particular any personal information — and for complying with the site's terms and applicable law (including the GDPR where it applies). Not affiliated with, endorsed by, or sponsored by SimplyHired or Indeed.

***

**Keywords:** SimplyHired scraper · SimplyHired API · SimplyHired job scraper · scrape SimplyHired · SimplyHired data extraction · job scraper · job board scraper · salary data scraper · SimplyHired jobs export · SimplyHired CSV Excel JSON · job monitoring · job alerts · lead generation · hiring data · international job scraper · no-code scraper · MCP tool for AI agents · market research

# Actor input Schema

## `query` (type: `string`):

Keywords to search for. Separate multiple searches with commas — each runs as its own search and results are merged and de-duplicated.

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

City, state, zip code or 'Remote'. Leave empty for all locations.

## `market` (type: `string`):

Which SimplyHired country site to search. Each market has its own job listings.

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

Paste SimplyHired search or job URLs to scrape directly. The market is auto-detected from the domain. Detail-page URLs work here too.

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

Maximum number of records to return. Set 0 for unlimited (bounded by how many the search has).

## `ignoreUrlFailures` (type: `boolean`):

Skip URLs that cannot be interpreted instead of failing the whole run.

## `jobType` (type: `array`):

Keep only jobs matching these employment types.

## `workLocation` (type: `array`):

Keep only remote or hybrid jobs.

## `datePosted` (type: `integer`):

Keep only jobs posted within the last N days. Leave empty for all dates.

## `minimumSalary` (type: `integer`):

Keep only jobs with a max salary at or above this threshold (annual, in the local currency).

## `requireContact` (type: `string`):

Keep only records that include a contact. off = keep everything; email / phone = require that channel; either = at least one; both = email and phone.

## `includeDetails` (type: `boolean`):

Fetch each job's detail page for the full description, structured salary, geo coordinates, qualifications, and more. Turn off for the fastest, cheapest runs.

## `descriptionFormat` (type: `string`):

Which representation(s) of the job description to include.

## `compact` (type: `boolean`):

Emit only the core fields (id, title, url, company, location, salary, type, date). Ideal for AI agents and MCP clients.

## `excludeEmptyFields` (type: `boolean`):

Remove null, empty-string and empty-array fields from each record.

## `incrementalMode` (type: `boolean`):

Track state between runs and tag every record with a changeType (NEW / UPDATED / UNCHANGED / EXPIRED).

## `stateKey` (type: `string`):

Stable name for the tracked search. Leave empty to derive one automatically from your search settings.

## `emitUnchanged` (type: `boolean`):

Also emit records that have not changed since the previous run.

## `emitExpired` (type: `boolean`):

Emit records for jobs present last run but gone now.

## `telegramToken` (type: `string`):

Bot token from @BotFather.

## `telegramChatId` (type: `string`):

Chat or channel ID, e.g. "-100123456789" or "@yourchannel".

## `slackWebhookUrl` (type: `string`):

Slack incoming-webhook URL.

## `discordWebhookUrl` (type: `string`):

Discord incoming-webhook URL.

## `webhookUrl` (type: `string`):

Any HTTPS endpoint. Receives a JSON POST with the matched jobs — works with n8n, Make and Zapier.

## `webhookHeaders` (type: `object`):

Extra headers for the webhook request, e.g. {"Authorization": "Bearer xyz"}.

## `notificationLimit` (type: `integer`):

How many jobs to include in each notification message.

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

Usually not needed — this scraper passes without a proxy. Enable only if you see persistent blocks.

## `maxRequestRetries` (type: `integer`):

How many times to retry a failed request before giving up on it.

## Actor input object example

```json
{
  "query": "data scientist, machine learning",
  "location": "New York, NY",
  "market": "US",
  "maxResults": 25,
  "ignoreUrlFailures": true,
  "requireContact": "off",
  "includeDetails": true,
  "descriptionFormat": "all",
  "compact": false,
  "excludeEmptyFields": false,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "notificationLimit": 5,
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "maxRequestRetries": 3
}
```

# Actor output Schema

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

No description

## `allItems` (type: `string`):

No description

# 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 = {
    "query": "software engineer",
    "location": ""
};

// Run the Actor and wait for it to finish
const run = await client.actor("corvuslab/simplyhired-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 = {
    "query": "software engineer",
    "location": "",
}

# Run the Actor and wait for it to finish
run = client.actor("corvuslab/simplyhired-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 '{
  "query": "software engineer",
  "location": ""
}' |
apify call corvuslab/simplyhired-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,corvuslab/simplyhired-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/t4MDa9ymtZoFvFxcO/builds/6Vkkg8FZw6T91LUKX/openapi.json
