# Remote Jobs Scraper - 7 Boards, Salaries & Leads (`scrapesage/remote-jobs-scraper`) Actor

Aggregate remote jobs from RemoteOK, Remotive, WeWorkRemotely, Himalayas, Jobicy, Arbeitnow & Working Nomads in one run: salary, skills, location, full description & apply link. Filter by keyword, salary & date. Company leads + monitoring for new jobs. JSON, CSV, Excel.

- **URL**: https://apify.com/scrapesage/remote-jobs-scraper.md
- **Developed by:** [Scrape Sage](https://apify.com/scrapesage) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 remote job listings

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/platform/actors/running/actors-in-store#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

## Remote Jobs Scraper — 7 Boards in One Run (Salaries, Skills & Company Leads)

Aggregate **remote job listings from the 7 biggest remote job boards in a single run** — **RemoteOK, Remotive, WeWorkRemotely, Himalayas, Jobicy, Arbeitnow and Working Nomads** — normalized into one clean dataset with **salaries, skills, candidate-location & timezone restrictions, full descriptions and apply links**. Optionally turn every hiring company into a **ready-to-contact B2B lead** (website, emails, phone, socials) and run it on a schedule to capture **only newly posted jobs**.

No login, no API key, no browser — fast JSON extraction from public endpoints with high reliability. Every source is keyless and the actor keeps running even if one board is temporarily unavailable.

### Why this remote jobs scraper?

Most remote-job scrapers cover a single board and return a thin row. This actor merges **seven** boards, de-duplicates the same role re-posted across them, and ships the **richest, most complete remote-jobs dataset in the category** — with structured salary, normalized job type, skills, and the company-lead layer no single-board scraper has.

| Data | Single-board scrapers | This actor |
|---|---|---|
| Boards covered in one run | 1 | ✅ **7** (RemoteOK, Remotive, WeWorkRemotely, Himalayas, Jobicy, Arbeitnow, Working Nomads) |
| Structured salary (min/max/currency/period) | ❌ rarely | ✅ parsed even from free-text salary strings |
| Skills / tags | partial | ✅ |
| Candidate-location & **timezone** restrictions | ❌ | ✅ |
| Normalized job type (full-time/contract/intern…) | ❌ | ✅ |
| Full job description (clean text + optional HTML) | partial | ✅ |
| Cross-board de-duplication | ❌ | ✅ |
| **Hiring-company leads** (website, emails, phone, socials, lead score) | ❌ | ✅ opt-in |
| Monitor mode — only new jobs | ❌ | ✅ |
| Filter by keyword, category, location, salary, date | partial | ✅ |

### Use cases

- **Job boards & aggregators** — power your own remote-work board, newsletter, Slack/Telegram channel or app with fresh, structured listings from seven sources at once.
- **Lead generation** — companies hiring remotely are buying: ATS/HR tools, dev agencies, recruiters, relocation/PEO/payroll, coworking and SaaS. Score them by hiring volume and reach them directly with `enrichCompanyContacts` (`emails`, `phone`, `website`, `socialLinks`, `leadScore`).
- **Recruiting & sourcing** — track new roles by stack (`python`, `react`, `golang`), seniority and region; spot which companies are scaling.
- **Market & salary intelligence** — analyze remote salary ranges, in-demand skills, and hiring trends by category and candidate region.
- **Job alerts** — schedule the actor with **monitor mode** to push only newly posted jobs into a CRM, sheet, or chat.

### How to use

1. [Sign up for Apify](https://console.apify.com/sign-up) — the free plan is enough to try this actor.
2. Open the **Remote Jobs Scraper**, add search keywords (or leave empty for the latest jobs), pick boards/filters, and click **Start**.
3. Watch results stream into the dataset table.
4. **Export** as JSON, CSV, Excel, XML, or RSS — or pull results programmatically via the [Apify API](https://docs.apify.com/api/v2).

### Input

```json
{
    "searchQueries": ["python", "react"],
    "sources": ["remoteok", "remotive", "weworkremotely", "himalayas", "jobicy", "arbeitnow", "workingnomads"],
    "candidateLocation": ["USA", "Worldwide"],
    "jobType": "full-time",
    "salaryMin": 80000,
    "postedWithinDays": 7,
    "outputType": "all",
    "maxItems": 300,
    "enrichCompanyContacts": true
}
```

- **searchQueries** — keywords matched against title, company, skills and description (ANY match). Leave empty to pull the latest remote jobs from every selected board.
- **sources** — which boards to aggregate (`remoteok`, `remotive`, `weworkremotely`, `himalayas`, `jobicy`, `arbeitnow`, `workingnomads`). Empty = all 7.
- **categories** — filter by category/industry/tags (`software development`, `marketing`, `design`, `customer support`, `sales`, `data`, …).
- **candidateLocation** — filter by where candidates may be based (`USA`, `Europe`, `United Kingdom`, `LATAM`, `Worldwide`). Worldwide/Anywhere jobs always pass.
- **companyNames** — keep only jobs from specific employers.
- **jobType / seniority / salaryMin / postedWithinDays** — narrow the results. `salaryMin` keeps only jobs whose published salary clears the floor.
- **outputType** *(default `jobs`)* — `jobs`, `companies` (deduplicated hiring-company leads), or `all`.
- **maxItems / maxItemsPerSource** — output cap, and how many to pull per board before filtering (raise it for narrow keyword searches).
- **includeDescriptionHtml** *(default false)* — also keep the raw HTML description.
- **deduplicateAcrossSources** *(default true)* — drop the same role when it appears on more than one board.
- **enrichCompanyContacts** *(default false)* — derive each company's website from the job links/apply URL and crawl it (home + contact/about) for emails, phone and socials, then assign a 0–100 lead score. Job boards never expose company emails — this is the only way to get them.
- **monitorMode / monitorKey** — output only jobs not seen in previous runs (see below).

### Output

By default you get **one clean, dense table of remote jobs** (`type: "job"`). Set `outputType` to `companies` for deduplicated hiring-company leads (`type: "company"`), or `all` for both.

A job record:

```json
{
    "type": "job",
    "source": "remotive",
    "sourceLabel": "Remotive",
    "id": "remotive:2090991",
    "title": "Senior Python Engineer",
    "company": "Quinncia Inc",
    "companyLogo": "https://remotive.com/job/2090991/logo",
    "url": "https://remotive.com/remote-jobs/software-development/senior-python-engineer-2090991",
    "applyUrl": "https://remotive.com/remote-jobs/software-development/senior-python-engineer-2090991",
    "category": "Software Development",
    "categories": ["Software Development"],
    "tags": ["python", "django", "graphql", "react", "aws"],
    "jobType": "Full-time",
    "seniority": "Senior",
    "isRemote": true,
    "candidateLocation": "USA",
    "locationRestrictions": ["USA"],
    "timezoneRestrictions": [-8, -7, -6, -5],
    "salaryMin": 120000,
    "salaryMax": 160000,
    "salaryCurrency": "USD",
    "salaryPeriod": "yearly",
    "salaryLabel": "USD 120k–160k/year",
    "description": "We are looking for a Senior Python Engineer to…",
    "publishedAt": "2026-06-16T06:59:30.000Z",
    "scrapedAt": "2026-06-17T12:00:00.000Z"
}
```

A company lead record (`type: "company"`) carries `company`, `companyLogo`, `jobCount`, the `sources` it posts on, `topTags`, `sampleJobTitles`, and — with `enrichCompanyContacts` — `website`, `domain`, `emails`, `phones`, `socialLinks` and a 0–100 `leadScore`.

#### What to expect (field coverage)

These are aggregated, organizer-entered listings, so some fields are present only when the company published them. A blank field means the source didn't provide it — nothing is dropped, so you always get the richest record available.

| Field group | Coverage |
|---|---|
| title, company, url, apply link, source, posting date | ~100% |
| skills/tags, category, candidate location | usually present |
| structured salary | when the board or salary text publishes it (strongest on Himalayas, Jobicy, RemoteOK, Remotive) |
| timezone restrictions, seniority | Himalayas / Jobicy |
| company emails & phone | with `enrichCompanyContacts`, when the company's website lists them |

### Monitor only new jobs

Turn on **monitorMode** and the actor remembers job ids across runs (in a named key-value store) and outputs **only jobs it hasn't seen before** — ideal for alerts and incremental syncs. It works **alongside** [Apify Schedules](https://docs.apify.com/platform/schedules): the schedule decides *when* to run, monitor mode decides *what's new*. Use a distinct `monitorKey` per saved search so separate monitors keep independent memory.

### Automate & schedule

Run this actor on autopilot and pull results into your own stack:

- **[Apify API](https://docs.apify.com/api/v2)** — start runs, fetch datasets, and manage schedules over REST.
- **[apify-client for JavaScript](https://docs.apify.com/api/client/js/)** and **[apify-client for Python](https://docs.apify.com/api/client/python/)** — official SDKs.
- **[Schedules](https://docs.apify.com/platform/schedules)** — run it hourly/daily to capture new remote jobs the moment they post; pair with monitor mode for clean new-only output.
- **[Webhooks](https://docs.apify.com/platform/integrations/webhooks)** — trigger downstream actions (CRM import, Slack alert, email sequence) the moment a run finishes.

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'MY_APIFY_TOKEN' });

const run = await client.actor('scrapesage/remote-jobs-scraper').call({
    searchQueries: ['python'],
    candidateLocation: ['USA'],
    monitorMode: true,
    monitorKey: 'python-usa',
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Got ${items.length} new remote jobs`);
```

### Integrate with any app

Connect the dataset to 5,000+ apps — no code required:

- **[Make](https://docs.apify.com/platform/integrations/make)** — multi-step automation scenarios.
- **[Zapier](https://docs.apify.com/platform/integrations/zapier)** — push new jobs or company leads straight into your CRM.
- **[Slack](https://docs.apify.com/platform/integrations/slack)** — get notified when a monitored search finds new jobs.
- **[Google Drive / Sheets](https://docs.apify.com/platform/integrations/drive)** — auto-export every run to a spreadsheet.
- **[Airbyte](https://docs.apify.com/platform/integrations/airbyte)** — pipe results into your data warehouse.
- **[GitHub](https://docs.apify.com/platform/integrations/github)** — trigger runs from commits or releases.

### Use with AI assistants (MCP)

The output is clean, LLM-ready JSON. Call this actor from Claude, ChatGPT, or any agent framework through the **[Apify MCP server](https://docs.apify.com/platform/integrations/mcp)** — ask your assistant to "find new remote Python jobs in the US over $120k and list the hiring companies' contacts" and let it run this scraper for you.

### Agent-ready: autonomous payments (x402 & Skyfire)

This actor is **agent-ready** — AI agents can discover it, run it, and **pay for it autonomously**, with no Apify account and no human in the loop. It uses [pay-per-event](https://docs.apify.com/platform/actors/publishing/monetize/pay-per-event) pricing and [limited permissions](https://docs.apify.com/platform/actors/development/permissions), so it qualifies for Apify's agentic-payment standards:

- **[x402](https://docs.apify.com/platform/integrations/x402)** — an open, HTTP-native payment protocol. Agents pay per run in USDC on the Base network directly through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp) — no account, no API key.
- **[Skyfire](https://docs.apify.com/platform/integrations/skyfire)** — agent-to-service payments for fully autonomous AI-agent workflows.

Building an AI agent, MCP tool, or autonomous data pipeline? This scraper is ready to plug in and pay as it goes.

### More scrapers from scrapesage

Build a complete **jobs & hiring-intelligence stack**:

- **[Multi-ATS Job Scraper](https://apify.com/scrapesage/multi-ats-job-scraper)** — jobs from Greenhouse, Lever, Ashby, SmartRecruiters & Workday company boards.
- **[LinkedIn Jobs Scraper](https://apify.com/scrapesage/linkedin-jobs-scraper)** — LinkedIn job postings as hiring-intent signals.
- **[Seek Job Scraper](https://apify.com/scrapesage/seek-job-scraper)** — Australia & New Zealand jobs, salaries & company leads.
- **[BuiltIn Jobs Scraper](https://apify.com/scrapesage/builtin-jobs-scraper)** — US tech & startup jobs.
- **[Y Combinator Scraper](https://apify.com/scrapesage/ycombinator-scraper)** — YC startups and their open roles.
- **[GitHub Scraper](https://apify.com/scrapesage/github-scraper)** — developers and open-source projects (great for technical sourcing).
- **[Website Contact Scraper](https://apify.com/scrapesage/website-contact-scraper)** — emails, phones & socials from any list of company domains.
- **[Levels.fyi Scraper](https://apify.com/scrapesage/levels-fyi-scraper)** — tech salaries & compensation benchmarks.

### Tips

- **Narrow keyword searches**: raise `maxItemsPerSource` so each board returns enough candidates before filtering.
- **Company leads**: turn on `enrichCompanyContacts` and sort by `leadScore` to prioritize the companies with reachable contacts and the most open roles.
- **Recurring monitoring**: combine [Schedules](https://docs.apify.com/platform/schedules) + `monitorMode` + `postedWithinDays` for a clean daily new-jobs feed.
- **Proxies**: the default Apify proxy works for all sources; switch to Residential if RemoteOK or WeWorkRemotely get rate-limited from datacenter IPs.

### FAQ

**Which job boards does it cover?** RemoteOK, Remotive, WeWorkRemotely, Himalayas, Jobicy, Arbeitnow and Working Nomads — all in a single run, de-duplicated into one dataset.

**Do I need API keys for the boards?** No. Every source is a public, keyless endpoint. No login or browser needed.

**Can I get only new jobs?** Yes — enable `monitorMode` and schedule the actor. It outputs only jobs not seen in previous runs.

**Where do company emails come from?** Never from the job boards (they don't publish them). With `enrichCompanyContacts` on, the actor finds the company's own website from the job's links and extracts publicly listed contact details — the same thing a human visitor would see.

**Can I export to Google Sheets, CSV, or Excel?** Yes — one click in the dataset view, or automatically on every run via the [Google Drive integration](https://docs.apify.com/platform/integrations/drive).

**A field is empty — why?** Some listings don't publish a salary, timezone, or seniority. Fields are blank only when the source didn't provide them — never because the scraper skipped them.

**Is scraping these boards legal?** This actor collects publicly available data only. You are responsible for using the data in compliance with applicable laws (e.g. GDPR/CCPA for personal data) and each source's terms.

### Need help?

Open an issue on the actor's **Issues** tab, or visit the [Apify help center](https://help.apify.com/). Feature requests are welcome — this actor is actively maintained.

# Actor input Schema

## `searchQueries` (type: `array`):

Keywords to match against job title, company, skills/tags and description (e.g. <code>python</code>, <code>product manager</code>, <code>devops</code>). A job matches if it contains ANY keyword. Leave empty to pull the latest remote jobs from every selected board.

## `sources` (type: `array`):

Which remote job boards to aggregate. Leave empty to use all 7. Options: <code>remoteok</code>, <code>remotive</code>, <code>weworkremotely</code>, <code>himalayas</code>, <code>jobicy</code>, <code>arbeitnow</code>, <code>workingnomads</code>.

## `categories` (type: `array`):

Optional category filter, matched against each job's category/industry and tags (e.g. <code>software development</code>, <code>marketing</code>, <code>design</code>, <code>customer support</code>, <code>sales</code>, <code>data</code>, <code>devops</code>, <code>finance</code>, <code>hr</code>, <code>writing</code>). A job matches if it contains ANY value.

## `candidateLocation` (type: `array`):

Filter by where candidates may be based, matched against the job's candidate-location restrictions (e.g. <code>USA</code>, <code>Europe</code>, <code>United Kingdom</code>, <code>Worldwide</code>, <code>LATAM</code>). Jobs open to <code>Worldwide</code>/<code>Anywhere</code> always pass.

## `companyNames` (type: `array`):

Optional: only keep jobs whose company name contains one of these values (case-insensitive). Handy for tracking specific employers.

## `jobType` (type: `string`):

Filter by employment type.

## `seniority` (type: `string`):

Optional seniority keyword, matched against the job's seniority field and title (e.g. <code>senior</code>, <code>junior</code>, <code>lead</code>, <code>entry</code>, <code>manager</code>).

## `salaryMin` (type: `integer`):

Only keep jobs whose published salary (upper bound) is at least this amount. Jobs without a published salary are dropped when this is set. Leave empty to include all.

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

Only include jobs posted within this many days. Leave empty for no date limit. Great for daily monitoring runs (e.g. <code>1</code> or <code>3</code>).

## `outputType` (type: `string`):

<code>jobs</code> = one row per remote job (default). <code>companies</code> = one deduplicated hiring-company lead per row. <code>all</code> = both, each row tagged with a <code>type</code> field.

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

Maximum number of job records to output (the cap is applied after filtering and de-duplication).

## `maxItemsPerSource` (type: `integer`):

How many jobs to fetch from each board before filtering. <code>0</code> = auto (scales to Max items). Raise it when using narrow keyword filters so enough candidates are gathered.

## `includeDescriptionHtml` (type: `boolean`):

Also include the original HTML description (<code>descriptionHtml</code>) alongside the clean plain-text <code>description</code>. Off by default for smaller, cleaner output.

## `deduplicateAcrossSources` (type: `boolean`):

Drop the same role when it appears on more than one board (matched by company + title), keeping the most recent. Turn off to see every board's copy.

## `enrichCompanyContacts` (type: `boolean`):

For each hiring company, derive its website from the job's links/apply URL and crawl it (home + contact/about, up to 3 pages) for contact emails, phone and social links, then assign a 0–100 lead score. Job boards never expose company emails — this is the only way to get them. Implies company-lead output.

## `monitorMode` (type: `boolean`):

Remember job ids across runs in a named key-value store and output ONLY jobs not seen before. Combine with an Apify Schedule (e.g. hourly/daily) for new-remote-job alerts. Works alongside Apify Schedules — it does not replace them.

## `monitorKey` (type: `string`):

Names the memory bucket for monitor mode. Use a distinct key per saved configuration (e.g. <code>python-usa</code>) so separate monitors don't share state.

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

Parallel requests for company-contact enrichment.

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

Proxy settings. The default Apify proxy works for all sources; switch to Residential if RemoteOK or WeWorkRemotely get rate-limited from datacenter IPs.

## Actor input object example

```json
{
  "searchQueries": [
    "python"
  ],
  "jobType": "",
  "outputType": "jobs",
  "maxItems": 200,
  "maxItemsPerSource": 0,
  "includeDescriptionHtml": false,
  "deduplicateAcrossSources": true,
  "enrichCompanyContacts": false,
  "monitorMode": false,
  "monitorKey": "default",
  "maxConcurrency": 5,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

All scraped remote job records and optional company lead records as JSON items in the default dataset.

# 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 = {
    "searchQueries": [
        "python"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapesage/remote-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 = {
    "searchQueries": ["python"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapesage/remote-jobs-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchQueries": [
    "python"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call scrapesage/remote-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=scrapesage/remote-jobs-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/0k8O371NreDnnvtHP/builds/uJaNqDfI2B1KME0KQ/openapi.json
