# Remote Jobs Scraper — RemoteOK, WeWorkRemotely, Jobicy (`actor-forge/remote-jobs`) Actor

Remote jobs from Remote OK, We Work Remotely, Jobicy and Arbeitnow in one deduplicated feed: title, company, where you can work from, job type, salary, posted date, apply link and description. Filter by keyword, location, salary and date. $0.80 per 1,000 jobs, ~19x cheaper than rivals.

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

## Pricing

from $0.80 / 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

## Remote Jobs Scraper — RemoteOK, WeWorkRemotely, Jobicy

Remote jobs from Remote OK, We Work Remotely, Jobicy and Arbeitnow in one deduplicated feed: title, company, where you can work from, job type, salary, posted date, apply link and description. Filter by keyword, location, salary and date. $0.80 per 1,000 jobs, ~19x cheaper than rivals.

**Remote jobs from four job boards in one clean, deduplicated feed.** This remote jobs scraper / remote job API reads **Remote OK**, **We Work Remotely** (WeWorkRemotely, all category feeds), **Jobicy** and **Arbeitnow** (remote roles only) through their public APIs and RSS feeds, and returns every work-from-home job in one schema: title, company, logo, **where you can work from** ("Anywhere in the World", "USA Only", "🇩🇪 Germany, 🇫🇷 France" and "Remote (US)" all normalized to a `locationRestrictions` list like `["Worldwide"]` or `["USA"]`), job type, category, tags, **salary min/max/currency/period** (structured where the board has it, parsed from the pay range otherwise), posted date, apply URL and the **full description as plain text and Markdown**. The same job posted on several boards comes back **once**, with every board listed in `sources`. Filter by **keywords**, excluded words, category, **country or region** ("Europe" matches jobs open to Germany, and vice versa), job type, **minimum salary** and **posted within N days**. Use it for job alerts and newsletters, a remote job board or Slack channel feed, recruiting and sourcing, labour-market and salary research, or as a job board scraper for AI agents. **$0.80 per 1,000 jobs**, about **19× cheaper** than the top-ranked remote jobs scraper ($15 per 1,000) and below every other remote-jobs actor we found. Duplicates, filtered-out jobs and boards that fail are never charged.

### What data does it return?

Every run outputs clean, schema-validated rows like these:

| title | company | locationRestrictions | jobType | salary | postedAt | sources |
| --- | --- | --- | --- | --- | --- | --- |
| Technical Account Manager | Expel | Worldwide | full-time | USD 114,300–165,700 / year | 2026-10-19 | weworkremotely |
| Sr. Software Engineer II / Tech lead, Agentic Platform | Samsara | Poland | full-time | PLN 638,350–751,000 / year | 2026-10-19 | jobicy |
| AI Trainer | iMerit Technology | UAE, Argentina, Austria, … | contract |  | 2026-10-18 | remoteok, weworkremotely |

### How much does it cost?

Transparent pay-per-event pricing — you only pay for what you get, and the
actor **always respects your run budget**: set a maximum total charge and it
stops cleanly at the cap instead of overrunning.

| Event | Price | Charged | Worked example |
| --- | --- | --- | --- |
| `job-result` | $0.0008 | per deduplicated job delivered (description, salary parsing and dedupe included) | 500 jobs = $0.40; 1,000 jobs = $0.80; a daily 200-job alert ≈ $4.80 per month |
| `apify-actor-start` | $0.00005 | per run per GB of memory (platform start fee) | One run at 512 MB = $0.000025 |

### Input options

| Field | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `sources` | array | no | `["remoteok","weworkremotely","jobicy","arbeitnow"]` | Which remote job boards to read. All four by default; the same job found on several boards is returned once. |
| `keywords` | array | no | `[]` | Keep jobs that mention ANY of these words in the title, tags, category or description (whole-word, case-insensitive). Leave empty for all jobs. Examples: python, product designer, customer support. |
| `excludeKeywords` | array | no | `[]` | Drop jobs whose title, company, tags or category contain any of these words (e.g. senior, sales, crypto). The description is not searched, so a passing mention doesn't remove a job. |
| `categories` | array | no | `[]` | Keep jobs whose category or tags match any of these (e.g. Design, DevOps, Marketing, Customer Support, Software Engineering). Each board has its own category names, so a few broad words work best. |
| `locations` | array | no | `[]` | Countries or regions you're eligible from, e.g. USA, UK, Germany, Europe, EMEA, LATAM, APAC, North America. A job open to 'Europe' matches 'Germany' and vice versa. Leave empty for all locations. |
| `includeWorldwide` | boolean | no | `true` | When filtering by location, also keep jobs open worldwide ('Anywhere') and jobs that don't state a location restriction. |
| `postedWithinDays` | integer | no | `7` | Only jobs posted in the last N days. 0 = any date. Jobs without a posting date are left out when this is set. |
| `salaryMin` | integer | no | — | Drop jobs whose published salary tops out below this yearly amount (hourly/monthly pay is converted to yearly; no currency conversion). Jobs without a salary are kept unless 'Only jobs with a salary' is on. |
| `requireSalary` | boolean | no | `false` | Keep only jobs that publish a salary or pay range. |
| `jobTypes` | array | no | `[]` | Keep only these employment types. Jobs whose type isn't stated are left out when this is set. |
| `maxJobs` | integer | no | `500` | Stop after this many jobs (newest first, after dedupe). You pay only for jobs delivered. |
| `includeDescription` | boolean | no | `true` | Add the full job description as plain text and as Markdown. Email addresses and phone numbers are removed from it. |
| `dedupe` | boolean | no | `true` | Return a job posted on several boards once (matched on company + title + compatible location), keeping the most complete copy and listing every board in 'sources'. |

### Limits & honest notes

- Sources: Remote OK, We Work Remotely, Jobicy and Arbeitnow. Himalayas and Remotive are not included: their API terms don't allow redistributing or reselling their jobs.
- Each board's feed holds its recent jobs only: Remote OK about the newest 100, We Work Remotely about 30 days across its category feeds, Jobicy pages back up to 3,000 jobs and Arbeitnow up to 3,000 listings per run (about 1 in 10 Arbeitnow listings is remote). Older listings can't be recovered.
- Arbeitnow is a European (mostly German) board; only jobs it flags as remote are returned, and many are remote within one country.
- Location restrictions are normalized from each board's wording. Unknown places (usually cities) are kept as written; a job that states no restriction has remoteType 'unspecified'.
- Salary appears only where the board or the posting publishes it. Structured board salaries are passed through; otherwise a pay range is parsed conservatively. The minimum-salary filter compares yearly amounts in the job's own currency (no exchange-rate conversion).
- Dedupe matches normalized company + title with compatible locations, so reworded copies of the same job ("Sr." vs "Senior", "(m/w/d)", "- Remote") merge, while the same title in different countries stays separate.
- When more jobs match than Maximum jobs, they're picked evenly across boards (newest first within each), so one busy board doesn't fill the run.
- Email addresses and phone numbers are removed from descriptions. Every row keeps the job's URL on the source board and an attribution line; please link back to the source board when you display the jobs, as each board's API terms ask.
- Respects your run budget: set a maximum total charge and the run stops cleanly at the cap, with no job charged twice.

### Changelog

- **2026-10-19** — Initial release: Remote OK, We Work Remotely (11 RSS feeds), Jobicy and Arbeitnow; location normalization, salary parsing, cross-board dedupe, keyword/category/location/salary/job-type/date filters, text and Markdown descriptions.

***

*Built and maintained by **ActorForge**. Reliability first: every actor in the
portfolio is monitored by an automated nightly self-test, and breakages are
typically fixed the same day.*

# Actor input Schema

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

Which remote job boards to read. All four by default; the same job found on several boards is returned once.

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

Keep jobs that mention ANY of these words in the title, tags, category or description (whole-word, case-insensitive). Leave empty for all jobs. Examples: python, product designer, customer support.

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

Drop jobs whose title, company, tags or category contain any of these words (e.g. senior, sales, crypto). The description is not searched, so a passing mention doesn't remove a job.

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

Keep jobs whose category or tags match any of these (e.g. Design, DevOps, Marketing, Customer Support, Software Engineering). Each board has its own category names, so a few broad words work best.

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

Countries or regions you're eligible from, e.g. USA, UK, Germany, Europe, EMEA, LATAM, APAC, North America. A job open to 'Europe' matches 'Germany' and vice versa. Leave empty for all locations.

## `includeWorldwide` (type: `boolean`):

When filtering by location, also keep jobs open worldwide ('Anywhere') and jobs that don't state a location restriction.

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

Only jobs posted in the last N days. 0 = any date. Jobs without a posting date are left out when this is set.

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

Drop jobs whose published salary tops out below this yearly amount (hourly/monthly pay is converted to yearly; no currency conversion). Jobs without a salary are kept unless 'Only jobs with a salary' is on.

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

Keep only jobs that publish a salary or pay range.

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

Keep only these employment types. Jobs whose type isn't stated are left out when this is set.

## `maxJobs` (type: `integer`):

Stop after this many jobs (newest first, after dedupe). You pay only for jobs delivered.

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

Add the full job description as plain text and as Markdown. Email addresses and phone numbers are removed from it.

## `dedupe` (type: `boolean`):

Return a job posted on several boards once (matched on company + title + compatible location), keeping the most complete copy and listing every board in 'sources'.

## Actor input object example

```json
{
  "sources": [
    "remoteok",
    "weworkremotely",
    "jobicy",
    "arbeitnow"
  ],
  "keywords": [
    "developer"
  ],
  "excludeKeywords": [],
  "categories": [],
  "locations": [],
  "includeWorldwide": true,
  "postedWithinDays": 7,
  "requireSalary": false,
  "jobTypes": [],
  "maxJobs": 500,
  "includeDescription": true,
  "dedupe": true
}
```

# Actor output Schema

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

One row per deduplicated remote job: title, company, location eligibility, job type, salary, posted date, apply URL, source board(s) and description.

## `summary` (type: `string`):

Per-board counts (read, matched, delivered), errors, duplicates merged and billing.

# 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 = {
    "keywords": [
        "developer"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("actor-forge/remote-jobs").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 = { "keywords": ["developer"] }

# Run the Actor and wait for it to finish
run = client.actor("actor-forge/remote-jobs").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 '{
  "keywords": [
    "developer"
  ]
}' |
apify call actor-forge/remote-jobs --silent --output-dataset

```

## MCP server setup

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

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/sG4bEyquN16snLiHh/builds/zlAXgVTKS3dPvX88m/openapi.json
