# Remote Jobs Aggregator — RemoteOK, Remotive, Himalayas, WWR +2 (`arthursbuisness/remote-jobs-aggregator-api`) Actor

- **URL**: https://apify.com/arthursbuisness/remote-jobs-aggregator-api.md
- **Developed by:** [Arthur](https://apify.com/arthursbuisness) (community)
- **Categories:** Jobs, Automation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.50 / 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/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

## Remote Jobs Aggregator — RemoteOK, Remotive, Himalayas, We Work Remotely, Jobicy, Arbeitnow

Six of the most-used remote job boards, one clean dataset. The actor reads each board's **public API or RSS feed** (no scraping of HTML pages, no login, no browser, no proxies), maps every listing onto the same schema, filters by keyword / category / region / date and **deduplicates** the same job posted on several boards. Ideal for building a remote-job board or newsletter, job alerts, market research on remote hiring and salaries, or feeding an LLM matching pipeline.

| source | feed | notes |
|---|---|---|
| RemoteOK | `remoteok.com/api` | newest ~100 jobs; salary in USD when set |
| Remotive | `remotive.com/api/remote-jobs` | category + candidate region; keyword search passed through |
| Himalayas | `himalayas.app/jobs/api` | cursor-paged (tens of thousands of jobs), salary, seniority, time zones |
| We Work Remotely | `weworkremotely.com/remote-jobs.rss` + category feeds | region, skills, expiry date |
| Jobicy | `jobicy.com/api/v2/remote-jobs` | 50 per request, industry, level, salary; keyword passed through as tag |
| Arbeitnow | `arbeitnow.com/api/job-board-api` | Europe/Germany-heavy; only listings flagged remote are kept |

### What you get

One row per job (`type: "job"`), identical fields for all sources:

| field | description |
|---|---|
| `source`, `id` | Board name and the board's own job id/slug |
| `title`, `company`, `company_logo` | Cleaned title and company name, logo URL when provided |
| `url`, `apply_url` | Job page on the source board (their terms ask that applications go through their page) |
| `location`, `remote_region` | Where the candidate must be based (e.g. `Worldwide`, `USA`, `Europe`, `Germany`) |
| `category`, `tags` | Board category plus skill/industry tags |
| `job_type`, `seniority` | `full_time`, `Contract`, `Full-Time`…; level when given |
| `salary_min`, `salary_max`, `salary_currency`, `salary_period`, `salary_text` | Structured pay when the board has it, else the board's free-text salary |
| `posted_at`, `expires_at` | ISO 8601 |
| `dedupe_key` | Normalised `title@company` used for cross-source deduplication |
| `description` | Full listing as clean plain text (headings and `- ` bullets kept); optional `description_html` |

A source that is down or blocks the request produces one `type: "error"` row — **free** — and the run continues with the next source.

Export as JSON, CSV or Excel, or push rows to Google Sheets, Make, Zapier, webhooks or your code via the Apify API.

### Input

| field | default | meaning |
|---|---|---|
| `sources` | all six | which boards to read, in order of preference (dedupe keeps the first) |
| `keywords` | — | keep jobs whose title/description/category/tags contain one of these |
| `excludeKeywords` | — | drop jobs whose title/description contains one of these |
| `categories` | — | keep jobs whose category/tags contain one of these |
| `locations` | — | keep jobs whose location/region contains one of these |
| `wwrCategories` | `["all"]` | WWR feeds to read (`programming`, `design`, `devops-sysadmin`, `sales-marketing`, `customer-support`, …) |
| `postedSince` | — | keep jobs published on/after `YYYY-MM-DD` |
| `dedupe` | true | drop duplicates by normalised title + company |
| `includeDescription` | true | store plain-text description |
| `includeHtml` | false | also store `description_html` |
| `maxItemsPerSource` | 200 | cap per source (after filters) |
| `maxItems` | 500 | cap for the run |

Example — worldwide engineering jobs from the last week:

```json
{
  "keywords": ["engineer", "developer"],
  "locations": ["Worldwide", "Anywhere", "Europe"],
  "postedSince": "2026-08-20",
  "wwrCategories": ["programming", "devops-sysadmin"],
  "maxItemsPerSource": 300
}
```

Schedule it hourly/daily and deduplicate on `source` + `id` (or on `dedupe_key`) to get only new listings.

### Pricing

Pay per event: **$0.0005 per stored job** ($0.50 per 1,000 jobs). Only rows actually written to the dataset are charged; error rows, duplicates and filtered-out jobs are free. Apify platform usage (a few seconds of compute per run) is billed separately by Apify.

### Limitations and fair use — please read

- The boards publish these feeds for free on the condition that you **credit them and link back** to the original listing (`url`), and route applications through their page. Please respect that in whatever you build; the actor keeps `url`/`apply_url` on every row for this reason.
- RemoteOK's API only exposes its newest ~100 jobs; Jobicy returns at most 50 per request. Himalayas and Arbeitnow are paged, so large `maxItemsPerSource` values work there.
- Category names and region wording differ per board (`Devops` vs `DevOps / Sysadmin`, `USA` vs `United States`): use short generic filter words.
- Deduplication is heuristic (normalised title + company); reposts with a changed title are not caught.
- Salary is structured only where the board provides numbers; free-text salaries stay in `salary_text`.
- RemoteOK occasionally serves mis-encoded emoji in descriptions; that comes from the source.
- Descriptions are the boards' own text; some boards truncate or add their own footer (e.g. RemoteOK's "please mention the word …" anti-spam line).

Not affiliated with any of the boards. Uses only their public feeds.

# Actor input Schema

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

Which public remote-job feeds to read. Default: all six.

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

Keep only jobs whose title, description, category or tags contain at least one of these words/phrases (case-insensitive). The first keyword is also passed to Remotive/Jobicy search so more matching jobs are fetched.

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

Drop jobs whose title or description contains any of these.

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

Keep only jobs whose category or tags contain one of these strings, e.g. 'engineering', 'design', 'marketing', 'customer support'. Category names differ per source, so use generic words.

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

Keep only jobs whose location or allowed region contains one of these strings, e.g. 'Worldwide', 'Anywhere', 'Europe', 'USA', 'Germany'.

## `wwrCategories` (type: `array`):

Which WWR RSS feeds to read: 'all' (the main feed, ~100 newest) or category feeds such as programming, design, devops-sysadmin, management, sales-marketing, product, customer-support, full-stack-programming, back-end-programming, front-end-programming, all-other.

## `postedSince` (type: `string`):

Keep only jobs published on or after this date.

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

Drop a job when the same normalised title + company was already stored from another (or the same) source. Sources are read in the order given, so put your preferred source first.

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

Store the full description as clean plain text. Turn off for a lighter dataset.

## `includeHtml` (type: `boolean`):

Also store the original HTML (description\_html).

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

Stop after this many stored jobs per source (after filters). RemoteOK exposes only its ~100 newest jobs; Jobicy 50 per request; Himalayas and Arbeitnow are paged.

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

Overall cap for the run.

## Actor input object example

```json
{
  "sources": [
    "remoteok",
    "remotive",
    "himalayas",
    "weworkremotely",
    "jobicy",
    "arbeitnow"
  ],
  "keywords": [
    "python",
    "data engineer"
  ],
  "wwrCategories": [
    "all"
  ],
  "dedupe": true,
  "includeDescription": true,
  "includeHtml": false,
  "maxItemsPerSource": 200,
  "maxItems": 500
}
```

# Actor output Schema

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

All items as JSON

## `resultsCsv` (type: `string`):

Same dataset as CSV — open in Excel/Sheets

# 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": [
        "python",
        "data engineer"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("arthursbuisness/remote-jobs-aggregator-api").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": [
        "python",
        "data engineer",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("arthursbuisness/remote-jobs-aggregator-api").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": [
    "python",
    "data engineer"
  ]
}' |
apify call arthursbuisness/remote-jobs-aggregator-api --silent --output-dataset

```

## MCP server setup

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

```

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/brRvocC96pjRhuqjI/builds/lKlORT4Of4cEVK6Ly/openapi.json
