# Remote Jobs Aggregator — RemoteOK, WWR, Himalayas, Jobicy (`fabrikit/remote-jobs-aggregator`) Actor

Remote jobs from six boards in one deduplicated feed: Remote OK, We Work Remotely, Himalayas, Jobicy, Remotive and Arbeitnow. Filter by keyword, category, region and job type; get title, company, location, salary, tags, dates and description. No API keys. From US$1.40 per 1,000 jobs.

- **URL**: https://apify.com/fabrikit/remote-jobs-aggregator.md
- **Developed by:** [Fabrikit](https://apify.com/fabrikit) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.40 / 1,000 job scrapeds

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 Aggregator — RemoteOK, We Work Remotely, Himalayas, Jobicy, Remotive & Arbeitnow

Remote Jobs Aggregator extracts remote job listings from six job boards — remoteok.com, weworkremotely.com, himalayas.app, jobicy.com, remotive.com and arbeitnow.com — into **one clean, deduplicated dataset** with the same fields for every board. Pick the boards, filter by keyword, category, region, job type and date, and download JSON, CSV or Excel. No API keys, no login, no browser.

**Pricing: US$1.40 per 1,000 jobs.** One event per unique job saved; platform compute is included.

### What you get

For every job: `title`, `company`, `companyLogo`, `url` (job page on the board), `applyUrl`, `category`, `tags`, normalised `jobType` (full-time, part-time, contract, freelance, internship), `seniority` when the board publishes a level, `location` as written by the board plus a `worldwide` flag, salary figures (`salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod`) when the board publishes them or `salaryText` when it only gives text, `postedAt` and `expiresAt` as ISO 8601 dates, the job `description` as plain text, and `source` / `sourceId` so you know where each job came from.

Duplicates are removed across boards: the same job is kept once whether it is matched by URL or by title + company.

### How it works

Each board publishes a public JSON API or RSS feed. The Actor reads the first page of every selected board in parallel, then takes jobs from the boards in turns so a small run already mixes all of them, and only requests further pages when it still needs jobs. Coverage per board on a full run (October 2026):

| Board | Feed | Depth |
|---|---|---|
| Remote OK | JSON API | ~100 newest jobs |
| We Work Remotely | RSS (main feed + 10 category feeds) | ~450 jobs |
| Himalayas | JSON API, cursor pagination | thousands (20 per page) |
| Jobicy | JSON API, cursor pagination | thousands (50 per page) |
| Arbeitnow | JSON API, page numbers | only postings flagged remote (about 7% of a mostly German/European board, 300 per page) |
| Remotive | JSON API | the public feed currently returns only its ~10 latest jobs |

`maxPagesPerSource` (default 10) caps the requests per board when your filters are strict.

### Input examples

Newest 50 remote jobs from all six boards (the default):

```json
{ "maxItems": 50 }
```

Senior-friendly engineering jobs mentioning Python or Go, open to Europe or worldwide, posted in the last two weeks:

```json
{
  "keywords": ["python", "golang", "go"],
  "categories": ["software development"],
  "regions": ["Europe"],
  "maxAgeDays": 14,
  "maxItems": 300
}
```

Full-time marketing and sales roles for US candidates from three boards, without descriptions:

```json
{
  "sources": ["weworkremotely", "jobicy", "himalayas"],
  "categories": ["marketing", "sales"],
  "regions": ["USA"],
  "jobTypes": ["full-time"],
  "includeDescription": false,
  "maxItems": 200
}
```

### Input fields

| Field | Description |
|---|---|
| `sources` | Boards to read: `remoteok`, `remotive`, `himalayas`, `weworkremotely`, `jobicy`, `arbeitnow`. Empty = all |
| `keywords` | Whole words matched in title, company, category and tags (any keyword matches). `searchInDescription` extends the match to the description |
| `categories` | Cross-board groups: software development, design, marketing, sales, customer support, product, devops, data, finance, hr, writing, legal, management, healthcare, education. Other text is matched literally |
| `regions` | Text matched against the board's location, with aliases for USA, UK, Europe, Canada, LATAM, APAC, Germany, India, Africa, Worldwide. `includeWorldwide` (default on) also keeps jobs open anywhere or without a location; turn it off for strict matching |
| `jobTypes` | full-time, part-time, contract, freelance, internship |
| `maxAgeDays` | Only jobs posted in the last N days |
| `includeDescription` | Plain-text description (on by default; no extra cost) |
| `maxItems` | Exact number of unique jobs to return (default 50) |
| `maxPagesPerSource` | Request cap per board (default 10) |
| `proxyConfiguration` | Off by default; the Actor switches to Apify residential proxies by itself if a board blocks the platform IP |

### Output example

```json
{
  "source": "weworkremotely",
  "sourceId": "vertex-marketing-group-distribution-engineer",
  "url": "https://weworkremotely.com/remote-jobs/vertex-marketing-group-distribution-engineer",
  "applyUrl": "https://weworkremotely.com/remote-jobs/vertex-marketing-group-distribution-engineer",
  "title": "Distribution Engineer",
  "company": "Vertex Marketing Group",
  "companyLogo": "https://wwr-pro.s3.amazonaws.com/logos/0171/6611/logo.gif",
  "category": "Back-End Programming",
  "tags": ["Back-End Programming", "Python", "API", "DevOps", "Android", "iOS"],
  "jobType": "full-time",
  "seniority": null,
  "location": "Anywhere in the World",
  "worldwide": true,
  "salaryMin": null,
  "salaryMax": null,
  "salaryCurrency": null,
  "salaryPeriod": null,
  "salaryText": null,
  "postedAt": "2026-10-20T11:32:37.000Z",
  "expiresAt": null,
  "description": "Headquarters: Bulgaria\nURL: https://vertexmg.com\nScale our distribution by code: a fleet of real devices, iPhones first and Android too, plus platform APIs and AI agents, posting across many accounts and surfaces. You work directly with the founder. ...",
  "scrapedAt": "2026-10-20T13:41:05.212Z"
}
```

A `SUMMARY` record in the key-value store lists, per board, how many pages were read, how many jobs matched your filters and how many were saved, plus any board that failed.

### Pricing

| Event | Price |
|---|---|
| Job saved (`job-result`) | US$1.40 per 1,000 |

Examples: 50 jobs = US$0.07; 1,000 jobs = US$1.40; 10,000 jobs = US$14.00. The Actor stops exactly at `maxItems` and never charges for duplicates or for jobs filtered out.

### Compared with alternatives

- Other multi-board remote job aggregators on Apify charge around US$2 per 1,000 jobs; single-board scrapers charge US$1 to US$4 per 1,000.
- If you only need one board, our single-site Actors are cheaper per run and have board-specific options: [Remote OK Jobs Scraper](https://apify.com/fabrikit/remoteok-jobs-scraper) and [We Work Remotely Scraper](https://apify.com/fabrikit/weworkremotely-scraper).
- Calling the six feeds yourself is free but you get six different schemas, HTML descriptions, mojibake, no deduplication and no filters. This Actor does that normalisation for you and keeps running when one board changes.

### Use cases

Remote job boards and newsletters, salary and demand research for remote roles, candidate alerts (schedule a daily run with `maxAgeDays: 1`), company lead lists of remote-first employers, feeding job data to AI agents and RAG pipelines.

### Integrations

Run it from the Apify API, schedule it, and export the dataset as JSON, CSV, Excel or RSS. Use the Apify integrations for n8n, Make, Zapier, Google Sheets and webhooks, or call it from AI agents through the Apify MCP server.

### FAQ

**Is this legal?** The Actor reads public feeds that the boards publish for developers and collects job ads, not personal data. Each board asks to be credited with a link back to the original posting: keep the `url` field (and `source`) when you re-publish, and do not use Remotive jobs to collect sign-ups or to feed other job boards (Remotive's API terms).

**Does it return recruiter e-mails or phone numbers?** No. E-mail addresses, phone numbers and personal profile links found in descriptions are removed, and no recruiter fields are output.

**Do I need a proxy?** No. All boards answered without a proxy during testing. If a board blocks the platform IP, the Actor retries through Apify residential proxies automatically.

**Why is `salaryMin` empty?** Most remote job ads do not publish figures. Jobicy, Himalayas and Remote OK publish numbers for some jobs; Remotive gives text (`salaryText`); We Work Remotely and Arbeitnow do not expose salaries in their feeds.

**Why does Remotive return so few jobs?** Its public feed currently serves about ten recent jobs regardless of parameters. The other five boards provide the depth.

**Why does `jobType` or `seniority` say null?** The board did not publish it. Values are normalised across boards from very different vocabularies (for example German contract names on Arbeitnow). Remote OK rarely publishes a job type or a location in its feed, so the `jobTypes` filter and a strict `regions` filter leave few Remote OK jobs.

**How often can I run it?** A full default run makes about 6 requests. Remotive asks for no more than a few calls per day, which a scheduled run every few hours respects.

### Changelog

- **0.1** (October 2026): first release — six boards, cross-board filters, URL and title+company deduplication, salary normalisation, personal-data scrubbing.

***

### En español

Agregador de **empleos remotos** desde seis bolsas (Remote OK, We Work Remotely, Himalayas, Jobicy, Remotive y Arbeitnow) en un solo dataset con los mismos campos, sin duplicados entre bolsas. Filtra por palabra clave, categoría, región, tipo de contrato y fecha; entrega título, empresa, ubicación, salario cuando la bolsa lo publica, etiquetas, fechas ISO y la descripción en texto plano sin correos ni teléfonos de personas. Sin API key ni proxy. **US$1,40 por 1.000 empleos.**

# Actor input Schema

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

Which boards to read. Leave empty for all six.

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

Keep jobs whose title, company, category or tags contain any of these words (whole words, case-insensitive; for example: python, react, product manager, c++). Leave empty for all jobs.

## `searchInDescription` (type: `boolean`):

Match keywords in the full job description as well (more results, less precise).

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

Job categories, matched across every board: software development, design, marketing, sales, customer support, product, devops, data, finance, hr, writing, legal, management, healthcare, education. Any other text is matched literally against the board's category and tags.

## `regions` (type: `array`):

Keep jobs whose location mentions any of these (for example: USA, Europe, UK, Canada, LATAM, APAC, Germany, Worldwide). Jobs open to candidates anywhere in the world, or without a location on the board, are kept too unless 'Include worldwide jobs' is off.

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

When regions are set, also keep jobs tagged as open worldwide / anywhere and jobs whose board gives no location (common on Remote OK). Turn off for strict region matching.

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

Only these employment types (normalised across boards). Leave empty for all.

## `maxAgeDays` (type: `integer`):

Only jobs posted in the last N days. Leave empty for any date.

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

Add the job description as plain text (e-mails, phone numbers and personal profile links removed). No extra requests or cost; turn off for a lighter dataset.

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

Stop after exactly this many unique jobs across all boards. The default run returns 50.

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

Safety cap on requests per board when filters are strict (Himalayas 20 jobs per page, Jobicy 50, Arbeitnow 300, We Work Remotely one feed per page; Remote OK and Remotive have a single page).

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

Not needed normally: the boards publish public feeds. If a board blocks the platform IP (HTTP 403/429/503), the Actor retries through Apify RESIDENTIAL proxies automatically.

## Actor input object example

```json
{
  "sources": [
    "remoteok",
    "remotive",
    "himalayas",
    "weworkremotely",
    "jobicy",
    "arbeitnow"
  ],
  "keywords": [],
  "searchInDescription": false,
  "categories": [],
  "regions": [],
  "includeWorldwide": true,
  "includeDescription": true,
  "maxItems": 50,
  "maxPagesPerSource": 10,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

All jobs collected during the run, deduplicated across boards

# 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 = {
    "sources": [
        "remoteok",
        "remotive",
        "himalayas",
        "weworkremotely",
        "jobicy",
        "arbeitnow"
    ],
    "keywords": [],
    "categories": [],
    "regions": [],
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("fabrikit/remote-jobs-aggregator").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 = {
    "sources": [
        "remoteok",
        "remotive",
        "himalayas",
        "weworkremotely",
        "jobicy",
        "arbeitnow",
    ],
    "keywords": [],
    "categories": [],
    "regions": [],
    "maxItems": 50,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("fabrikit/remote-jobs-aggregator").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 '{
  "sources": [
    "remoteok",
    "remotive",
    "himalayas",
    "weworkremotely",
    "jobicy",
    "arbeitnow"
  ],
  "keywords": [],
  "categories": [],
  "regions": [],
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call fabrikit/remote-jobs-aggregator --silent --output-dataset

```

## MCP server setup

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

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/j6mQ3F3VgcDK2vZ87/builds/5TDcUz3J0JYcfloeF/openapi.json
