# Remote Jobs & Work From Home Jobs: 5 Boards, Salaries, Alerts (`data-done-right/remote-jobs-scraper`) Actor

Remote jobs and work from home jobs from 5 boards with official public APIs and feeds (Remote OK, Jobicy, Working Nomads, Arbeitnow, 4dayweek.io) in one deduplicated schema. Parsed salaries, location limits, filters, and only new jobs since your last run.

- **URL**: https://apify.com/data-done-right/remote-jobs-scraper.md
- **Developed by:** [Data Done Right](https://apify.com/data-done-right) (community)
- **Categories:** Jobs, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.36 / 1,000 jobs

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Remote Jobs & Work From Home Jobs: 5 Boards, Salaries, Alerts

This **remote jobs scraper** collects remote job listings from **five job boards that publish an official public API or feed** (it reads the APIs and feeds, not web pages), merged into **one clean schema** with salaries, location restrictions, categories and a cross-board duplicate check. Run it daily with **Only jobs new since my last run** and you have a remote-job alert feed.

| Board | How we read it |
|---|---|
| **Remote OK** | official public API |
| **Jobicy** | official public API |
| **Working Nomads** | public API linked from their site |
| **Arbeitnow** | official public API (remote jobs only) |
| **4dayweek.io** | official public API (remote jobs only; employers with 4-day-week and similar schedule perks) |

No login, no scraping of web pages, no proxies needed.

### What data can you extract from remote job boards

- **One schema for all boards.** Same field names whatever the source: title, company, logo, company URL, category, tags, job type, seniority, location restrictions, salary, posted date, apply link, plain-text description.
- **Salaries that are usable.** Taken from the board's data when it has one, and detected in the job text when it does not (`$130,000 - $160,000`, `£46k–£54k`, `80k-100k USD`, hourly and monthly pay). Every job says where its salary came from (`salarySource`: `api` or `text`), plus a yearly equivalent (`salaryYearlyMin` / `salaryYearlyMax`) so you can filter and sort across boards.
- **Location restrictions.** `locationRestrictions` as a list (`Worldwide`, `USA`, `Europe`...), a `worldwide` flag and time zones where the board gives them (the boards mostly list a country or region; some jobs are open worldwide). Filter with *Location restriction contains*.
- **Cross-board de-duplication.** The same company and the same normalized title on two boards is returned once. `alsoOn` lists the other boards and `alsoOnUrls` links to them. Missing fields (salary, logo, tags) are filled from the other listing. You pay for one job, not two.
- **Filters:** keywords (title, category, tags), exclude keywords, categories, location restriction, job types, minimum yearly salary, only jobs with a salary, posted within N days, which boards.
- **Only new jobs.** Remembers what you already received (also across boards) and returns only new ones. Perfect for scheduled daily alerts.
- **Reliable by design.** Boards are fetched in parallel. If one board is down, the rest still arrive, and the run status names the failed board and why (also in the `NOTES` record). A `SUMMARY` record shows what each board returned.

### Output (one row per job)

A real row from a test run, merged from two boards (description shortened):

```json
{
  "source": "jobicy",
  "sourceJobId": "155685",
  "title": "Senior Customer Success Engineer",
  "company": "Cribl",
  "companyLogo": "https://jobicy.com/data/server-nyc0409/galaxy/mercury/2025/06/65d82c04-221.jpeg",
  "companyUrl": "https://cribl.io",
  "category": "Customer Support & Success",
  "categoryGroup": "Customer Support",
  "tags": ["Customer Success", "Data Analysis", "AWS", "Azure", "GCP", "SIEM"],
  "jobType": "full-time",
  "seniority": "Senior",
  "workSchedule": "unlimited_pto",
  "locationRestrictions": ["UK"],
  "worldwide": false,
  "timezones": [],
  "salaryMin": 80400,
  "salaryMax": 95000,
  "salaryCurrency": "GBP",
  "salaryPeriod": "YEAR",
  "salaryYearlyMin": 80400,
  "salaryYearlyMax": 95000,
  "salaryText": null,
  "salarySource": "api",
  "postedAt": "2026-10-16T17:09:31Z",
  "expiresAt": null,
  "applyUrl": "https://jobicy.com/jobs/155685-senior-customer-success-engineer-2",
  "sourceUrl": "https://jobicy.com/jobs/155685-senior-customer-success-engineer-2",
  "description": "Join the company that's building the telemetry infrastructure for the AI era...",
  "dedupeKey": "cribl|senior customer success engineer",
  "alsoOn": ["4dayweek"],
  "alsoOnUrls": {"4dayweek": "https://4dayweek.io/job/senior-customer-success-engineer-at-cribl-ae02e6ba"},
  "attribution": "Source: Jobicy (https://jobicy.com)"
}
```

`workSchedule` is only filled by 4dayweek.io (for example `4_day_week`, `9_day_fortnight`, `unlimited_pto`). Fields a board does not publish are `null` or empty, see "How complete is the data" below.

### How complete is the data

Share of rows with the field filled, from one test run of 1,505 jobs (this varies by day):

| Board | Logo | Company URL | Tags | Job type | Location | Salary | Posted date |
|---|---|---|---|---|---|---|---|
| Jobicy | 100% | 1% | 100% | 100% | 100% | 52% | 100% |
| 4dayweek.io | 98% | 98% | 100% | 25% | 100% | 62% | 100% |
| Remote OK | 2% | 4% | 99% | 4% | 46% | 27% | 100% |
| Arbeitnow | 0% | 0% | 100% | 95% | 95% | 1% | 100% |
| Working Nomads | 2% | 2% | 98% | 2% | 100% | 9% | 100% |

Overall about 45% of jobs had a salary (33% straight from the board's data, 12% detected in the job text). Titles, companies, links, descriptions and posting dates are always present.

### How to find remote jobs by keyword, salary and location

Set **Keywords**, **Location restriction contains**, **Minimum yearly salary** and **Posted within (days)**, then run. Turn on **Only jobs new since my last run** and schedule a daily run to get a remote-job alert feed.

### Work from home jobs: how to find them

Set **Location restriction contains** to `Worldwide`, **Posted within (days)** to `7`, and turn on **Only jobs new since my last run**. Schedule the Actor once a day and every run returns only the work from home jobs posted since the last one.

### Input example

```json
{
  "keywords": ["python", "data engineer"],
  "locationContains": ["Worldwide", "Europe"],
  "minSalary": 80000,
  "postedWithinDays": 14,
  "onlyNew": true,
  "maxItems": 100
}
```

### Use cases

- **Job seekers:** a daily list of new remote roles that match your skills, location and salary floor.
- **Recruiters and sourcers:** watch which companies are hiring remotely, and for what.
- **Newsletters and niche job boards:** a steady, de-duplicated feed (read the attribution rules below).
- **Market research:** remote salary bands by category, share of worldwide vs region-locked roles, and the 4-day-week market.

### Attribution: please read before you display these jobs

Each board allows use of its data on the condition that you credit it. Every row has `sourceUrl` and an `attribution` text for that. If you show these jobs to other people:

- **Link to the job's own page (`sourceUrl` / `applyUrl`) and name the source.** `applyUrl` is always the board's own listing page; we do not replace it with the employer's link.
- **Remote OK:** link back to the Remote OK job URL with a normal (followed) link and mention Remote OK as the source. Do not use the Remote OK logo.
- **Jobicy:** keep Jobicy as the source with the Jobicy job URL, and send applicants through that URL.
- **Arbeitnow, 4dayweek.io:** link back to arbeitnow.com / 4dayweek.io.
- Do not present jobs as your own postings.

### Honest limits

- **Only five boards.** We include only boards whose public API or feed terms allow this kind of use. Some well-known boards are left out on purpose because their terms forbid passing their jobs on to aggregators or third-party sites (for example Himalayas, Remotive and We Work Remotely), or because they require per-app registration.
- **Overlap between boards is small.** In our test about 2 to 3 in 100 listings appeared on more than one board (36 of 1,505). De-duplication works, but do not expect large savings.
- **Each board shows a different window.** Remote OK ~100 latest jobs, Working Nomads ~50, Jobicy the last 7 days (200 per page), Arbeitnow and 4dayweek.io are paginated (set *Max pages per board*). This is a feed of recent remote jobs, not a full archive.
- **Arbeitnow is a German board.** Only listings it marks remote are returned, and most of them are in Germany or Europe.
- **Location data is whatever the board publishes.** Remote OK often leaves it empty, so those jobs have no restriction listed and never match a location filter. Arbeitnow and Remote OK give a place that may be the employer's base, not a restriction.
- **Detected salaries are best-effort.** Text detection only reads explicit ranges with a currency (`$90,000 - $110,000`); it can miss unusual formats, and pay for non-salary things can occasionally be misread. Currencies are not converted: the minimum salary filter compares the amount per year in the job's own currency. Check `salarySource` when it matters.
- **Categories are mapped** from each board's own names into shared groups (`categoryGroup`) with simple rules, and are not perfect.
- **Same-title postings from one company** on the same board stay separate (different openings or locations).
- **Only new** treats a job already delivered from any board as seen, even after it disappears from the first board. Re-posts of an old job under a new ID on the same board count as new. Schedule runs at most once per hour (Jobicy's rule for automated polling); once a day is plenty for alerts.
- The Actor does not apply to jobs or visit employer pages.

### Remote jobs API

Call it from the Apify API, Python, JavaScript, Make, Zapier or n8n. Example with the Apify Python client:

```python
from apify_client import ApifyClient

run = ApifyClient("<APIFY_TOKEN>").actor("data-done-right/remote-jobs-scraper").call(run_input={
    "keywords": ["python"], "locationContains": ["Worldwide"], "minSalary": 100000, "postedWithinDays": 7})
```

Then read the jobs from the run's default dataset.

### Use it in Claude, ChatGPT and Cursor

Connect Apify's MCP server (mcp.apify.com) and your AI assistant can search remote jobs for you. For example: "find remote Python jobs open worldwide that state a salary over 100k and were posted this week." The main inputs are `keywords`, `locationContains` and `minSalary`.

### How much does it cost

Pay per event: **$0.0017 per job delivered** (about $1.70 per 1,000 jobs, after de-duplication and filters), plus the standard Apify start fee. Paid Apify plans get 10% (Silver) to 20% (Gold and up) off. **Max jobs** caps your cost.

### FAQ

#### Where can I find work from home jobs?

Run this Actor with **Location restriction contains** set to `Worldwide`. It reads five remote job boards in one run and returns work from home jobs in one clean list, with salaries where the board or the job text gives one.

#### Is there a remote jobs API?

Yes. Call the Actor from the Apify API or an Apify client (see the "Remote jobs API" example above) and read the jobs as JSON from the dataset. Filters for keyword, location, salary and posting date are inputs.

#### Are there 4 day work week jobs?

Yes. The 4dayweek.io board is included, and its jobs carry a `workSchedule` field such as `4_day_week`. Select only that board to see 4 day work week remote jobs.

#### Which remote job boards does it cover?

Remote OK, Jobicy, Working Nomads, Arbeitnow and 4dayweek.io. Himalayas, Remotive and We Work Remotely are left out on purpose, because their terms do not allow passing their jobs on to aggregators.

#### Is it legal to scrape remote job boards?

It does not scrape web pages. It reads the public APIs and feeds these boards publish, and each row carries an attribution text and the board's own link. You must follow the attribution rules shown above if you display the jobs. This is not legal advice.

#### Can I get remote jobs with a salary?

Yes. Use **Only jobs with a salary** and **Minimum yearly salary**. About 45% of jobs had a salary in our test run (33% from the board's data, 12% detected in the job text), so expect those filters to keep a minority of rows.

#### How do I get only new remote jobs every day?

Turn on **Only jobs new since my last run** and schedule the Actor. It remembers jobs across all boards, so a job that appears on two boards is delivered once.

#### Do I need a login or API key?

No.

#### Does it apply to jobs for me?

No. It only lists jobs; it does not apply to them or visit employer pages.

### Related tools

- **[ATS Jobs Scraper](https://apify.com/data-done-right/ats-jobs-scraper)**: every open job from company career sites on Greenhouse, Lever, Ashby and Workday.
- **[Hiring Signals](https://apify.com/data-done-right/hiring-signals)**: which tech and teams a company is hiring for.
- **Google Sheets Import & Export**: send the dataset to a Google Sheet.

# Actor input Schema

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

Which boards to collect. Leave empty for all five: remoteok, jobicy, workingnomads, arbeitnow, 4dayweek.

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

Keep jobs whose title, category or tags contain any of these words (e.g. python, designer, customer success). Leave empty for all jobs.

## `excludeKeywords` (type: `array`):

Drop jobs whose title contains any of these words (e.g. intern, junior).

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

Keep only these job groups: Engineering, Data & AI, Design, Product, Marketing, Sales, Customer Support, Finance & Legal, People & HR, Operations, Writing & Education, Healthcare, Other. A board's own category name or a tag also matches.

## `locationContains` (type: `array`):

Keep jobs open to candidates in any of these places, e.g. Worldwide, Europe, USA, Germany. 'Worldwide' also matches jobs the board marks as anywhere. Boards that do not publish a restriction (some Remote OK jobs) never match.

## `jobTypes` (type: `array`):

Keep only these types: full-time, part-time, contract, freelance, internship, temporary, permanent. Jobs whose type the board does not publish are dropped when this is set. Example: full-time, contract.

## `minSalary` (type: `integer`):

Keep jobs whose salary range reaches at least this amount per year. Hourly, daily, weekly and monthly pay is converted to yearly. Currencies are NOT converted, so 80000 means 80000 in the job's own currency. Jobs without a stated or detected salary are dropped when this is set.

## `requireSalary` (type: `boolean`):

Keep only jobs that state a salary (from the board's data or detected in the job text).

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

Keep only jobs posted in the last N days. Jobs without a posting date are dropped when this is set.

## `onlyNew` (type: `boolean`):

Remembers the jobs you already received and returns only new ones. Schedule the Actor daily for job alerts. The first run returns everything that matches. A job already delivered from one board is not delivered again when it shows up on another board.

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

Only used with 'Only jobs new'. Runs with the same filters share memory automatically. Type a name here to keep separate memory for separate alerts that use the same filters.

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

Stop after this many jobs (newest first). Also caps your cost.

## `maxPagesPerSource` (type: `integer`):

How many pages to read from boards that paginate (Jobicy 200 jobs per page, Arbeitnow 300, 4dayweek.io 100). Raise it to dig deeper into the backlog.

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

Plain-text job description. Turn off for smaller output.

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

Not needed: these boards publish open APIs. Enable only if a board blocks the default network.

## Actor input object example

```json
{
  "requireSalary": false,
  "onlyNew": false,
  "maxItems": 100,
  "maxPagesPerSource": 3,
  "includeDescription": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

All result items of this run (the default dataset), as JSON, CSV, Excel and more.

## `records` (type: `string`):

Key-value store records: the run summary, notes on any problems, and any files.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("data-done-right/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 = {}

# Run the Actor and wait for it to finish
run = client.actor("data-done-right/remote-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 '{}' |
apify call data-done-right/remote-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,data-done-right/remote-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/h08PAnfHUFBDTUAT3/builds/cGxx0FoMKtJpXJIgz/openapi.json
