# Remote Jobs Aggregator: We Work Remotely & Remote OK Scraper (`delgadolegacy/remote-jobs-aggregator`) Actor

Scrape remote jobs from We Work Remotely & Remote OK into one clean, deduplicated dataset. Keyword, tag, region & salary filters, structured salary, only-new-jobs monitor mode, source attribution on every job. Official feeds, no login, no proxies. From $0.80 per 1,000 jobs.

- **URL**: https://apify.com/delgadolegacy/remote-jobs-aggregator.md
- **Developed by:** [Delgado Legacy Partners](https://apify.com/delgadolegacy) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.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.
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 Aggregator: We Work Remotely & Remote OK jobs scraper

**Remote Jobs Aggregator** collects **remote job listings from We Work Remotely and Remote OK into one clean, deduplicated dataset**. Filter by keyword, tag or category, region and minimum salary. You get **structured salary** (min, max, currency, interval), and **monitor mode** returns only jobs you haven't seen before. Every job carries its **source URL and a ready-made attribution link**. It works as a We Work Remotely scraper and a Remote OK scraper in one run. No login, no API key, no proxies. **Pay per result from $0.80 per 1,000 jobs, no start fee.**

All data comes from each board's own official public feed (We Work Remotely RSS and the Remote OK JSON API). Both boards allow reuse with attribution.

### Why use this remote jobs scraper

- **2 boards, 1 schema.** Every job has the same fields, whichever board it came from. Field names match our [Career Page Jobs Scraper](https://apify.com/delgadolegacy/career-page-jobs-scraper), so you can merge the two datasets.
- **No duplicates.** The same job (same company + title) on both boards becomes one item, and the other listing is kept in `alsoListedOn`.
- **Structured salary.** Taken from Remote OK's salary field, or parsed from the description (`$120,000 – $150,000`, `$45-60/hr`, `USD 3,000 - 3,500 per month`). Min, max, currency and interval (year, month or hour) are separate fields.
- **Only new jobs.** Schedule it daily with `onlyNewJobs` to get a feed of fresh remote jobs for Slack, email, Google Sheets, Airtable or your own job board.
- **Privacy-safe.** No emails, phone numbers or other contact details. Any found in descriptions are replaced with `[contact removed]`.
- **Polite and official.** Official feeds only, a clear User-Agent, 1.5 s between requests to the same board, and robots.txt respected.
- **Fast.** A full run reads about 575 jobs (Oct 24, 2026) and takes about a minute on the Apify cloud.
- **One-click test.** The prefilled input (python / react / devops, last 30 days, up to 200 jobs) returns results immediately.

### Use cases

- **Job seekers:** one daily list of new remote Python, React, DevOps, design or marketing jobs, with a salary filter.
- **Remote job boards and newsletters:** a fresh, deduplicated feed with attribution fields ready to display.
- **Recruiters and sales teams:** see which companies are hiring remotely right now (company, role, salary, tags).
- **Market research:** remote salary ranges and demand by skill.
- **AI agents and automations:** clean JSON for n8n, Make, Zapier or an LLM pipeline.

### How to scrape remote jobs

1. Leave both boards selected, or pick one.
2. Optional filters: keywords, tags/categories, locations/regions, minimum salary, posted within N days.
3. Click **Start**, then download the results as JSON, CSV or Excel, or use the API.
4. For a daily feed: tick **Only new jobs**, give the monitor a name, and add a **Schedule**.

### Input

| Field | What it does |
|---|---|
| `sources` | `weworkremotely`, `remoteok` (default: both). The order decides which copy is kept when a job is on several boards. |
| `keywords` | Keep jobs whose title, company or tags contain ANY of these words (whole word, case-insensitive). |
| `excludeKeywords` | Drop jobs whose title contains any of these, e.g. `senior`, `intern`. |
| `searchInDescription` | Also match keywords in the description. |
| `tags` | Keep jobs with any of these tags or categories, e.g. `design`, `devops`, `customer support`. |
| `locations` | Keep jobs whose location/region contains any of these, e.g. `USA`, `Europe`, `Canada`. |
| `includeWorldwide` | With a location filter, also keep "Anywhere in the World" jobs (default on). |
| `remoteOnly` | Default on. Drops the rare listing that is clearly marked on-site. |
| `minSalary` | Minimum annual salary (hourly and monthly pay are annualized: ×2080 and ×12), in the job's own currency. Jobs without a salary are dropped when this is set. |
| `onlyWithSalary` | Keep only jobs that show a salary. |
| `postedWithinDays` | Only jobs posted in the last N days. |
| `dedupeAcrossBoards` | Merge the same job across boards (default on). |
| `onlyNewJobs` + `monitorName` | Monitor mode: return only jobs not returned before under this monitor name. |
| `includeDescription` | Include the plain-text description (default on). |
| `maxJobs` | Cap on saved jobs, newest first (0 = no cap). |

Example: remote engineering jobs open to the US paying $100k+, posted in the last 30 days:

```json
{
  "keywords": ["engineer", "developer"],
  "excludeKeywords": ["intern"],
  "locations": ["USA", "United States"],
  "minSalary": 100000,
  "postedWithinDays": 30,
  "maxJobs": 200
}
```

### Sample results (real rows from our test run, Oct 24, 2026)

| Board | Company | Title | Salary | Posted |
|---|---|---|---|---|
| We Work Remotely | Discord | QA/DevOps Engineer | USD 156,000–175,500 / year | 2026-10-23 |
| We Work Remotely | Vercel | Senior Manager, Solutions Architect | USD 280,000–350,000 / year | 2026-10-03 |
| We Work Remotely | PlanetScale | Enterprise Support Engineer | USD 120,000–200,000 / year | 2026-10-18 |
| Remote OK | Lemon.io | Senior DevOps Engineer | USD 50,000–150,000 / year | 2026-10-22 |
| Remote OK | Wrapbook | Senior Software Engineer II Applied AI | (not published) | 2026-10-15 |

### Output (one item per job)

```json
{
  "source": "weworkremotely",
  "jobId": "discord-qa-devops-engineer",
  "company": "Discord",
  "title": "QA/DevOps Engineer",
  "department": "DevOps and Sysadmin",
  "tags": ["devops and sysadmin"],
  "location": "Anywhere in the World",
  "region": "Anywhere in the World",
  "country": null,
  "isRemote": true,
  "workplaceType": "Remote",
  "employmentType": "Full-Time",
  "salaryMin": 156000,
  "salaryMax": 175500,
  "salaryCurrency": "USD",
  "salaryInterval": "year",
  "salaryText": "$156,000—$175,500",
  "salarySource": "description",
  "postedAt": "2026-10-23T07:31:21+00:00",
  "expiresAt": "2026-11-22T07:31:21+00:00",
  "jobUrl": "https://weworkremotely.com/remote-jobs/discord-qa-devops-engineer",
  "applyUrl": "https://weworkremotely.com/remote-jobs/discord-qa-devops-engineer",
  "sourceName": "We Work Remotely",
  "sourceUrl": "https://weworkremotely.com/remote-jobs/discord-qa-devops-engineer",
  "attributionText": "Source: We Work Remotely",
  "attributionHtml": "Source: <a href=\"https://weworkremotely.com/remote-jobs/discord-qa-devops-engineer\">We Work Remotely</a>",
  "attributionRequirement": "WWR public RSS feed: attribute links back to We Work Remotely.",
  "alsoListedOn": [],
  "descriptionText": "Headquarters: San Francisco Bay Area or Remote (U.S.)\n\nDiscord has a highly engaged community ...",
  "scrapedAt": "2026-10-24T11:05:00+00:00"
}
```

(Example values shortened.) A **RUN_SUMMARY** record in the key-value store gives per-board counts (fetched, after dedupe, matched, saved) and any errors.

### Data sources, terms and attribution (please read if you republish)

Both boards publish these feeds for public reuse **on condition that you credit them**. Each item has `sourceName`, `sourceUrl` and a ready-made `attributionHtml` link. **If you show these jobs on a website, app or newsletter, keep a visible link back to `sourceUrl` and name the board.**

| Board | Feed used | What the board asks (checked Oct 24, 2026) |
|---|---|---|
| **We Work Remotely** | Official RSS feeds (main + 11 category feeds) | "Anyone can use the feed, all we ask is that you attribute the links back to We Work Remotely." robots.txt allows these paths. |
| **Remote OK** | Official public API `remoteok.com/api` | Link back to the job URL on Remote OK **with a normal (followed) link, no `rel="nofollow"`**, and mention **Remote OK** as the source, or Remote OK may suspend API access. Don't use the Remote OK logo without permission (this Actor outputs no logos). robots.txt asks for a 1 s crawl delay, and we wait 1.5 s. |

This Actor collects **no contact data**: there are no email, phone or recruiter fields, and emails and phone numbers inside descriptions are replaced with `[contact removed]`. Descriptions are otherwise the board's own text. Apply through `applyUrl` / `jobUrl` on the source board.

### Pricing

**Pay per result**, live since Oct 24, 2026: you pay only for jobs saved to the dataset. No start fee, no monthly rental.

| Apify plan | Price per 1,000 jobs |
|---|---|
| Free | $1.20 |
| Bronze | $1.00 |
| Silver | $0.90 |
| Gold, Platinum, Diamond | $0.80 |

Apify platform usage is included. Set *Maximum cost per run* in the run options to cap spend; the run stops charging at your limit.

### Notes and limits

- Each run reads what the boards publish **right now**: about 100 newest jobs from Remote OK and several hundred from We Work Remotely (main + category feeds). For a growing history, schedule the Actor with monitor mode.
- Remote OK often leaves `location` empty, so a location filter skips those jobs. Leave the location filter empty to keep them.
- Salary parsing from free text is best-effort. `salarySource` tells you whether it came from the board (`board`) or the description (`description`).
- Duplicate detection uses normalized company + title.
- Not affiliated with We Work Remotely or Remote OK.

### FAQ

**Do I need an API key or proxies?** No. Both feeds are public.

**How do I get only new jobs every day?** Set `onlyNewJobs: true` and a `monitorName`, then create a daily Schedule. Each run returns only jobs that earlier runs with the same monitor name didn't return.

**Can I use the data on my own job board?** Both boards allow reuse with attribution. Keep the `attributionHtml` link (followed, no nofollow, for Remote OK) next to each job. You're responsible for following each board's terms.

**Why only 2 boards?** We only include boards whose official feed allows reuse in a tool like this. We left out boards whose terms forbid passing jobs on to other aggregators or limit use to personal, non-commercial purposes.

**Found a bug or want a board added?** Open an issue on the Issues tab.

### More free tools from the same developer

- [Career Page Jobs Scraper](https://apify.com/delgadolegacy/career-page-jobs-scraper): every open job straight from company career pages on Greenhouse, Lever, Ashby and Workable.
- [SAM.gov Contract Opportunities Scraper](https://apify.com/delgadolegacy/samgov-opportunities): US federal contract opportunities (RFPs, solicitations, awards), no API key.
- [PDF Text Extractor](https://apify.com/delgadolegacy/pdf-text-extractor): text, per-page text, keyword hits and metadata from PDF URLs in bulk, no start fee.
- [Sitemap URL Extractor](https://apify.com/delgadolegacy/sitemap-url-extractor): every URL from a website's sitemap.xml with lastmod, hreflang and regex/date filters.

# Actor input Schema

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

Which boards to collect from. Order also sets which board's copy is kept when the same job is listed on several boards.

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

Keep jobs whose title, company or tags contain ANY of these words (whole-word, case-insensitive), e.g. 'python', 'react', 'customer support'. Leave empty for all jobs.

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

Drop jobs whose title contains any of these words, e.g. 'senior', 'intern', 'manager'.

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

Also look for keywords in the full job description (finds more jobs, less precise).

## `tags` (type: `array`):

Keep jobs with ANY of these tags or categories, e.g. 'design', 'devops', 'marketing', 'customer support', 'full-stack'. Matches Remote OK tags and WWR categories/skills.

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

Keep jobs whose location or region text contains any of these, e.g. 'USA', 'Europe', 'United Kingdom', 'Canada', 'Berlin'. Leave empty for all.

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

When a location filter is set, also keep jobs open anywhere in the world.

## `remoteOnly` (type: `boolean`):

Both boards are remote-only, so this rarely changes anything. Keeps only jobs flagged remote.

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

Keep only jobs whose (annualized) top of salary range is at least this amount, in the job's own currency. Jobs without a salary are dropped when this is set. 0 = no filter.

## `onlyWithSalary` (type: `boolean`):

Keep only jobs that state a salary (from the board's salary field or parsed from the description).

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

Keep only jobs posted in the last N days. 0 = no limit.

## `dedupeAcrossBoards` (type: `boolean`):

Merge the same job (same company + title) listed on several boards into one item; other listings go to 'alsoListedOn'.

## `onlyNewJobs` (type: `boolean`):

Return only jobs not delivered in earlier runs with the same monitor name. Schedule the Actor (e.g. daily) to get a feed of new remote jobs.

## `monitorName` (type: `string`):

Name for the 'only new jobs' memory. Use different names for different searches.

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

Include the plain-text description. Emails and phone numbers are always removed.

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

Maximum number of jobs to save (newest first). 0 = no limit.

## Actor input object example

```json
{
  "sources": [
    "weworkremotely",
    "remoteok"
  ],
  "keywords": [
    "python",
    "react",
    "devops"
  ],
  "excludeKeywords": [],
  "searchInDescription": false,
  "tags": [],
  "locations": [],
  "includeWorldwide": true,
  "remoteOnly": true,
  "minSalary": 0,
  "onlyWithSalary": false,
  "postedWithinDays": 30,
  "dedupeAcrossBoards": true,
  "onlyNewJobs": false,
  "monitorName": "default",
  "includeDescription": true,
  "maxJobs": 200
}
```

# Actor output Schema

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

One item per job (company, title, location, remote flag, structured salary, tags, posted date, source URL and attribution, description).

## `runSummary` (type: `string`):

Per-board counts (fetched, after dedupe, matched, saved), errors, and each board's attribution terms.

# 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": [
        "weworkremotely",
        "remoteok"
    ],
    "keywords": [
        "python",
        "react",
        "devops"
    ],
    "excludeKeywords": [],
    "tags": [],
    "locations": [],
    "postedWithinDays": 30,
    "maxJobs": 200
};

// Run the Actor and wait for it to finish
const run = await client.actor("delgadolegacy/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": [
        "weworkremotely",
        "remoteok",
    ],
    "keywords": [
        "python",
        "react",
        "devops",
    ],
    "excludeKeywords": [],
    "tags": [],
    "locations": [],
    "postedWithinDays": 30,
    "maxJobs": 200,
}

# Run the Actor and wait for it to finish
run = client.actor("delgadolegacy/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": [
    "weworkremotely",
    "remoteok"
  ],
  "keywords": [
    "python",
    "react",
    "devops"
  ],
  "excludeKeywords": [],
  "tags": [],
  "locations": [],
  "postedWithinDays": 30,
  "maxJobs": 200
}' |
apify call delgadolegacy/remote-jobs-aggregator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,delgadolegacy/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/YyfD02ssIP3gP1k1O/builds/alt5uyFTq6dpkdhWx/openapi.json
