# Remote Job Board Scraper API | Remote OK + WWR Job Postings (`aurelix/remote-jobs-scraper`) Actor

Scrape remote job postings at $0.90 per 1,000 jobs, cheaper than the alternatives ($1.00 plus platform usage, or $1.99), with cross-board dedupe, a minimum-salary filter and a new-jobs-only mode. Remote OK and We Work Remotely jobs in one list, no login: title, company, tags, regions, salary, date.

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

## Pricing

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

### What is Remote Job Board Scraper?

**Get remote jobs from Remote OK and We Work Remotely in one deduplicated list (title, company, tags, regions, salary) for $0.90 per 1,000 jobs, no login.**

For job boards, newsletters and job-search tools. Filter by keywords, categories, regions or time zones and a minimum yearly salary, and get only new jobs on scheduled runs. Your first run with the example input costs about $0.005 (4 jobs in our test run).

[![Remote Job Board Scraper: example output from a real run](https://api.apify.com/v2/key-value-stores/twkCCtTWzsi8fVbx5/records/remote-jobs-scraper-card-v2.png)](https://console.apify.com/actors/1gtF7PjOsvTeCLpWR?addFromActorId=1gtF7PjOsvTeCLpWR)

[![Remote Job Board Scraper: 75-second demo video](https://api.apify.com/v2/key-value-stores/twkCCtTWzsi8fVbx5/records/remote-jobs-scraper-demo-thumb-v1.png)](https://api.apify.com/v2/key-value-stores/twkCCtTWzsi8fVbx5/records/remote-jobs-scraper-demo-v1.mp4)

**[▶ Watch the 75-second demo](https://api.apify.com/v2/key-value-stores/twkCCtTWzsi8fVbx5/records/remote-jobs-scraper-demo-v1.mp4)**

| | |
|---|---|
| **Sources** | Remote OK (API) and We Work Remotely (public RSS) |
| **Filters** | Keywords, 12 categories, regions or time zones, worldwide on/off, employment type, minimum yearly salary |
| **Output** | 28 fields per job; JSON, CSV, Excel, API |
| **Automate** | Schedules, webhooks, Zapier, Make, n8n, Google Sheets, MCP for AI agents |
| **Price** | $0.90 per 1,000 jobs ($0.60 per 1,000 jobs on paid Apify plans) |
| **Login needed** | No |

### Daily monitor: only what's new, every morning

Set it once, get only the new jobs every morning. With **Only new jobs since last run** on, the first run returns everything that matches; each later run skips jobs that earlier runs already returned, so you pay only for new ones.

```json
{
  "keywords": [
    "python",
    "data engineer"
  ],
  "incremental": true,
  "stateKey": "python-data-daily"
}
```

1. Paste this input into the **Input** tab (JSON view) and click **Save as a new task**; it appears under **Saved tasks**.
2. Open the task from **Saved tasks** and click **Schedule**.
3. Choose **Daily**, pick the hour, and save.

**Cost example:** 2 keywords, about 20 new jobs a day ≈ $0.57/month on the free plan ($0.39 on paid plans): one run a day for 30 days, start fee included. The first run returns everything that matches, so it costs more.

Add a Slack incoming-webhook URL in `slackWebhookUrl` (or any URL in `webhookUrl`) to get a short digest of each run's new jobs; nothing is sent when a run finds nothing.

### Why Remote Job Board Scraper users pick this one

- **Cheaper than the alternatives.** $0.90 per 1,000 jobs, no platform usage billed on top.
- **Two boards, one schema.** Normalised category and employment type on every job.
- **No duplicates.** A job on both boards comes back once.
- **Salary and region filters.** Minimum yearly salary; regions with or without worldwide jobs.
- **New jobs only.** Matched across both boards.

### Get started in 3 steps

1. Pick the sources (both by default) and optionally add keywords such as 'python' or 'product designer'.
2. Narrow it with categories, regions (e.g. 'Canada', 'Europe'), employment types or a minimum yearly salary; turn on 'Only new jobs since last run' for a daily feed.
3. Click Start, then download JSON, CSV or Excel, or schedule the run and send new jobs to Google Sheets, Slack, Zapier, Make or n8n.

**[▶ Try it with the example input](https://console.apify.com/actors/1gtF7PjOsvTeCLpWR?addFromActorId=1gtF7PjOsvTeCLpWR)**

The form opens with an example input already filled in: that run costs about $0.005 on the free plan.

### How much does it cost to scrape remote jobs?

Pay per event: you pay only for what the run returns, plus a small start fee. Bronze, Silver, Gold and higher Apify plans pay less per result.

| Jobs | Free plan | Paid plans (Bronze, Silver, Gold) |
|---|---|---|
| 100 | $0.091 | $0.061 |
| 1,000 | $0.90 | $0.60 |
| 10,000 | $9.00 | $6.00 |

Totals include the $0.001 start fee per run, rounded to the cent (amounts under $0.10 to four decimals). Apify's free plan includes $5 of credit a month, enough for about 5,500 jobs.

Duplicates across boards are charged once. Each run's start fee covers reading both boards when filters match little or nothing.

#### Billing events

| Event | Free plan | Paid plans (Bronze, Silver, Gold) |
|---|---|---|
| `job-result` | $0.90 per 1,000 jobs | $0.60 per 1,000 jobs |
| `apify-actor-start` | $0.001 per run | $0.001 per run |

### Benchmarks: how we compare

| Test | Input | Result |
|---|---|---|
| Default run on Apify | empty input | 199 jobs (We Work Remotely 100, Remote OK 99) in 7.4 s |
| Smaller cap on Apify | maxResultsPerSource 40 | 80 jobs (40 per board) in 7.2 s |
| Run that matches nothing | keyword that matches no job | 0 jobs in 6.6 s; only the start fee charged |
| Everything both boards publish | maxResultsPerSource 0 | 589 jobs (We Work Remotely 490, Remote OK 99) from 602 source postings |
| Duplicates removed in that run | maxResultsPerSource 0 | 13: 7 jobs found on both boards, 6 repeated on the same board |
| Jobs that publish a salary | maxResultsPerSource 0 | 21 of 589 (3.6%): 21 of 99 on Remote OK, 0 of 490 on We Work Remotely |
| Field accuracy | 10 sampled jobs | 10 of 10 matched the board's API or feed and the live job page |
| Second incremental run | incremental on, same filters | 0 jobs repeated out of 589 seen |
| One board unavailable | empty input | Remote OK's 99 jobs returned; status names the failed board |
| Both boards down or rate-limited | empty input | Run ends cleanly with a 'No jobs' status; no job charged |
| First run from the Store | prefilled input | 4 jobs for $0.005 |

Measured by our own test runs of this Actor against the live boards: run times on the Apify platform, counts and accuracy from local runs of the same code, one run per row. The board-down rows simulate failed and rate-limited requests. Job counts change daily as the boards post and expire jobs.

### What data you get

**Remote Job Board Scraper** reads the public feeds of Remote OK and We Work Remotely and turns them into one deduplicated list: title, company, normalised category, tags, employment type, allowed regions with a worldwide flag, salary where published, posted date, job link and an attribution line. Filter by keyword, 12 categories, region or time zone, employment type and minimum yearly salary. A job posted on both boards comes back once, with the other board under also_listed_on.

- Title, company, company logo, normalised category and the board's own category, tags/skills
- Employment type (normalised + as published); a seniority column that stays empty, since neither board publishes seniority
- Allowed locations/regions and a worldwide flag
- Salary min/max, currency and interval where published
- Posted and expiry dates in ISO 8601 UTC
- Job link on the source board, attribution line, and other boards carrying the same job
- Description as text and HTML (optional)

| title | company | category | employment_type | locations | salary_min | salary_max | salary_currency | posted_at | source |
|---|---|---|---|---|---|---|---|---|---|
| AI ML Engineer | Docusketch | software-development |  | \[] | 10000.0 | 120000.0 | USD | 2026-11-02T10:43:35Z | Remote OK |
| RevOps Manager | ClickGUARD Inc. | management | CONTRACT | \["Anywhere in the World"] |  |  |  | 2026-11-03T19:09:15Z | We Work Remotely |
| Front End Developer | Edconic | software-development |  | \[] | 80000.0 | 100000.0 | USD | 2026-10-28T21:53:15Z | Remote OK |

One full job record, exactly as a real run returned it (long text and lists shortened here). From a real run:

```json
{
  "job_id": "remoteok:1137475",
  "source": "Remote OK",
  "source_site": "https://remoteok.com",
  "title": "Senior React Full stack Developer",
  "company": "Lemon.io",
  "company_logo_url": null,
  "category": "software-development",
  "category_raw": null,
  "tags": [
    "dev",
    "engineer",
    "remote",
    "... [10 more]"
  ],
  "employment_type": "FULL_TIME",
  "employment_type_raw": "full time",
  "seniority": null,
  "locations": [],
  "worldwide": true,
  "salary_min": 80000,
  "salary_max": 200000,
  "salary_currency": "USD",
  "salary_interval": "year",
  "posted_at": "2026-10-09T13:09:18Z",
  "expires_at": null,
  "apply_url": "https://remoteok.com/remote-jobs/remote-senior-react-full-stack-developer-lemon-io-1137475",
  "job_url": "https://remoteok.com/remote-jobs/remote-senior-react-full-stack-developer-lemon-io-1137475",
  "description_text": "Are you a talented Senior Developer looking for a remote job that lets you show your skills and get decent compensation?... [4786 more characters]",
  "description_html": "<p>Are you a talented Senior Developer looking for a remote job that lets you show your skills and get decent compensati... [5758 more characters]",
  "attribution": "Job via Remote OK (https://remoteok.com)",
  "also_listed_on": [
    {
      "source": "We Work Remotely",
      "job_url": "https://weworkremotely.com/remote-jobs/lemon-io-senior-react-full-stack-developer-7"
    }
  ],
  "source_url": "https://remoteok.com/remote-jobs/remote-senior-react-full-stack-developer-lemon-io-1137475",
  "scraped_at": "2026-11-04T06:24:01Z"
}
```

### Use cases

- Remote job boards and newsletters pulling fresh postings daily with the new-jobs-only mode
- Job seekers getting new remote roles in their region sent to Slack or Google Sheets
- Recruiters and researchers tracking which remote roles and salaries are being advertised

### Use-case recipes

#### Daily remote jobs feed for a newsletter or job board

Turn on 'Only new jobs since last run', pick your categories and schedule the run once a day. Each run returns only jobs you have not received before, across both boards. Use `title`, `company`, `job_url` and `attribution` for each listing, and send `job_url` to the apply button as the boards ask. Raise the per-board cap if you want older postings too.

```json
{
  "categories": [
    "software-development",
    "data-ai"
  ],
  "incremental": true,
  "maxResultsPerSource": 50,
  "includeDescription": false
}
```

#### Remote roles open to one country, sent to Slack

A job seeker in Canada sets regions to Canada and keeps worldwide jobs in. Add a Slack webhook URL and a daily schedule to get the count and the top 10 new jobs in a channel. Check `locations` and `worldwide` to see why each job matched.

```json
{
  "keywords": [
    "python",
    "backend"
  ],
  "regions": [
    "Canada"
  ],
  "includeWorldwide": true,
  "incremental": true,
  "maxResultsPerSource": 25
}
```

#### Salary snapshot for remote engineering roles

Compensation researchers read Remote OK only, since We Work Remotely's feed has no salary field. Set a minimum yearly salary and switch off descriptions for a small file. Pivot `salary_min` and `salary_max` by `category` or by tags in a spreadsheet.

```json
{
  "sources": [
    "remoteok"
  ],
  "minSalary": 50000,
  "includeDescription": false,
  "maxResultsPerSource": 100
}
```

#### Find companies that keep hiring remotely

Recruiters and sales teams run a wide, cheap pull without descriptions. Count jobs per `company` and keep the ones posting several roles. Feed those companies' domains into the Hiring Signal Monitor to follow every role they open on their own career site.

```json
{
  "maxResultsPerSource": 100,
  "includeDescription": false
}
```

### Input

| Field | Type | What it does | Default |
|---|---|---|---|
| `keywords` (Keywords) | array | Keep jobs whose title or company contains at least one of these words (case-insensitive), e.g. \['python', 'data engineer']. |  |
| `maxResultsPerSource` (Max results per source) | integer | Upper limit of jobs returned per source after filters, newest first, e.g. 50. | 100 |
| `sources` (Sources) | array | Job boards to read: 'remoteok' (Remote OK), 'weworkremotely' (We Work Remotely). | \["remoteok", "weworkremotely"] |
| `categories` (Categories) | array | Keep jobs in these normalised categories, e.g. \['software-development', 'data-ai']. |  |
| `regions` (Regions or time zones) | array | Keep jobs whose allowed location mentions one of these words, e.g. \['USA', 'Canada', 'Europe', 'UTC']. |  |
| `includeWorldwide` (Include worldwide jobs in region filter) | boolean | When filtering by region, also keep jobs open to anyone anywhere ('Worldwide', 'Anywhere'). | true |

All 13 fields, with examples: see the **Input** tab.

### Use with AI agents (Apify MCP server, Claude, ChatGPT, n8n AI agent)

Remote Job Board Scraper is a ready-made tool for AI agents. Through the Apify MCP server an agent reads this Actor's input schema, fills in the input from your request, starts the run and reads the jobs back. You pay the same per-result price as a run started by hand, from your own Apify account.

#### Example prompts

- "Find remote Python and data engineering jobs open to people in Canada from Remote OK and We Work Remotely and give me a table with title, company, salary and link"
- "List remote design jobs posted on Remote OK and We Work Remotely, without duplicates, sorted newest first"
- "Get remote software development jobs that pay at least 100000 USD a year and show the salary range and job link for each"

#### Claude (claude.ai and Claude Desktop)

Open **Settings > Connectors**, choose **Add custom connector**, paste `https://mcp.apify.com/?tools=aurelix/remote-jobs-scraper` and sign in to Apify when asked. Then ask Claude one of the prompts above.

#### Claude Code, Cursor, VS Code and other MCP clients

```bash
claude mcp add --transport http apify "https://mcp.apify.com/?tools=aurelix/remote-jobs-scraper"
```

Clients configured with JSON take the same URL:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com/?tools=aurelix/remote-jobs-scraper"
    }
  }
}
```

A client without Apify sign-in sends the header `Authorization: Bearer <YOUR_APIFY_TOKEN>`; to run the server locally instead, use `npx -y @apify/actors-mcp-server --actors aurelix/remote-jobs-scraper` with `APIFY_TOKEN` set.

#### ChatGPT

Where your ChatGPT plan offers custom connectors (developer mode), add `https://mcp.apify.com/?tools=aurelix/remote-jobs-scraper` as a connector, sign in to Apify, and ask for the data in plain words.

#### n8n AI agent

Give an **AI Agent** node an **MCP Client Tool** with the endpoint `https://mcp.apify.com/?tools=aurelix/remote-jobs-scraper` and a Bearer credential holding your Apify token. The agent can then call Remote Job Board Scraper whenever a workflow step needs jobs; for a fixed, non-agent workflow use Apify's n8n node with **Run Actor** instead.

### Use it from AI agents (MCP), the API or no-code

#### Copy this to your AI assistant

```text
Use the Apify Actor aurelix/remote-jobs-scraper (Remote Job Board Scraper) through Apify's MCP server or API. Main input: keywords (Keywords); maxResultsPerSource (Max results per source). Example input: {"keywords": ["python", "data engineer"], "categories": ["software-development", "data-ai"], "regions": ["Canada", "USA"], "minSalary": 80000, "incremental": true}. Each result is one job with fields such as job_id, source, source_site, title, company, company_logo_url, category, category_raw. It costs $0.90 per 1,000 jobs on Apify's free plan plus a $0.001 start fee per run, and needs no login.
```

MCP server URL for this Actor: `https://mcp.apify.com/?tools=aurelix/remote-jobs-scraper` (setup for each client in the section above).

#### API

Start a run and read the dataset with Apify's REST API or the Python and JavaScript clients:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("aurelix/remote-jobs-scraper").call(run_input={'keywords': ['python', 'data engineer'], 'categories': ['software-development', 'data-ai'], 'regions': ['Canada', 'USA'], 'minSalary': 80000, 'incremental': True})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

#### No-code: schedule it in 3 clicks

Send the results to Google Sheets, Zapier, Make, n8n, Slack or any webhook URL.

1. Fill in the input, then click **Save as a new task**.
2. In the task, click **Schedule** and pick daily or weekly (Apify Schedules).
3. Turn on **Only new jobs since last run** so each run returns only what is new, and paste a Slack or webhook URL into **Slack webhook URL** / **Webhook URL** to get a digest of the new items (count plus the top 10) after every run.

Prefer n8n or Make? Ask in the **Issues** tab and we will share a ready-made workflow for it.

### FAQ

#### Can I scrape remote jobs without login?

Yes. It never logs in, so you need no job board account, password or cookies; only a free Apify account to run it.

#### Is there a remote jobs API?

You can use this Actor as one. Start it with Apify's REST API or the Python and JavaScript clients and read the results as JSON (see the code above), or call it from an AI agent through MCP.

#### How much does it cost to scrape remote jobs?

About $0.90 for 1,000 jobs on Apify's free plan and $0.60 on paid plans, start fee included. The free $5 monthly credit covers about 5,500 jobs.

#### Can I export remote jobs data to Excel or Google Sheets?

Yes. Download the results as Excel, CSV, JSON, XML or HTML from the run's **Storage** tab, or send them to Google Sheets with Apify's Google Sheets integration or the API.

#### Is it legal to scrape remote jobs?

It reads only public data any logged-out visitor can see: Remote OK's public API and We Work Remotely's public RSS feed, with an attribution line and source link on every job. It goes at a polite pace, never logs in and never solves CAPTCHAs. It returns job posting fields (title, company, tags, salary, dates, description, link); no candidate profiles; descriptions can name a recruiter or hiring contact (business contact information, B2B use only, see Lawful use). To have a record removed, open an issue on this Actor's Issues tab; if a board formally asks us to stop, this Actor will stop. You are responsible for using the data lawfully, incl. anti-spam and privacy laws; this is not legal advice.

#### Which boards are included, and why not others?

Remote OK (API) and We Work Remotely (public RSS). Each publishes its feed for reuse with a link back. Jobicy, Remotive, Himalayas, Working Nomads and Arbeitnow are left out because their terms forbid passing jobs on to other platforms or commercial reuse.

#### How do I credit the source?

Every job carries 'attribution' (e.g. 'Job via Remote OK (https://remoteok.com)') and 'job_url' on the source board. If you show the jobs publicly, show that credit and use job_url for the apply button, as the boards ask. Do not use the Remote OK logo; the name is fine.

#### How are duplicates detected?

By company and title, ignoring case and punctuation. The first board's record is kept; the others appear in also_listed_on with their links.

#### How does the region filter work?

It matches your words against each job's published allowed locations, such as 'USA', 'Europe', 'Canada' or 'Americas'. Jobs open worldwide are kept too unless you switch that off. Boards do not publish structured time zones, so 'UTC' matches only where the text says so.

#### Why is salary empty for some jobs?

Only about 4% of postings publish pay (about a fifth of Remote OK's; We Work Remotely's feed has no salary field). With a minimum salary set, jobs without a salary are dropped. Remote OK salaries are yearly USD.

#### How does 'new since last run' work?

The Actor remembers jobs it has returned for the same sources and filters (or the state name you set) and returns only unseen ones. A job seen on any board counts as seen. Jobs are forgotten 60 days after they were last seen.

#### What am I charged when nothing matches or a board is down?

Only the start fee. Jobs are charged one by one as they are saved, so a run with 0 matching jobs costs just that fee. If one board fails or rate-limits the run after retries, the other board's jobs are still returned and charged, and the status message names the board that failed. If both fail, the run ends with a 'No jobs' status and no job is charged.

#### Which text do keywords search?

The job title and company name only, case-insensitive. A job is kept if it contains any one of your keywords. Tags and descriptions are not searched. Matching is by text fragment, so 'java' also matches 'javascript'. For broad topics, the categories filter is usually more reliable.

#### How is the category decided?

By keyword rules applied to the title first, then to the board's own category, then to the tags. The first rule that matches wins, in a fixed order starting with software development. A job that matches no rule gets 'other'. The board's own category is kept in category_raw, where the board publishes one.

#### How does the minimum salary filter handle hourly or monthly pay?

It takes the top of the published range (or the single figure), converts it to a yearly amount (monthly x 12, weekly x 52, daily x 260, hourly x 2080) and compares it in the posting's own currency. Remote OK salaries are yearly USD. We Work Remotely's feed has no salary field, so setting a minimum salary returns Remote OK jobs only.

#### Why is a job with no location marked worldwide?

When a board publishes no location for a job, the Actor treats it as open worldwide, as do location texts such as 'Worldwide' or 'Anywhere'. In our test of everything both boards published, 53 of 99 Remote OK jobs had no location. With a region filter and 'Include worldwide jobs' on, these jobs are kept; switch it off to see only jobs that name your region.

#### Should I change 'Max results per source' for a daily feed?

The cap is applied before the new-jobs check, so each run looks only at the newest jobs per board, up to the cap. A daily run with the default 100 per board catches most new postings. Set it to 0 if you want every new job however old; in our test that meant 589 jobs on the first run.

#### Why are some columns always empty?

Each board publishes different fields. Neither board publishes seniority, so that column stays empty. In our test only We Work Remotely jobs carried a company logo and an expiry date, and only Remote OK jobs carried a salary. Missing values are null, never guessed.

#### How long does a run take?

Every run reads both boards in full before filtering, so run time hardly depends on your filters. On Apify a default run of 199 jobs took about 7 seconds and a run that matched nothing about the same.

### Lawful use

- B2B use only: descriptions are kept as the employer published them and can include a recruiter or hiring contact. That is business contact information; use it only for business purposes such as job search, hiring-market research or a relevant business enquiry, never for consumer marketing.
- No spam: contact people only with relevant, individual business messages, identify yourself, and honour every opt-out at once. Bulk unsolicited email built from this data is not allowed.
- You are responsible for complying with the anti-spam and privacy laws that apply to you and to the people you contact, including Canada's CASL, the US CAN-SPAM Act and the EU/UK GDPR (lawful basis, transparency, the right to object).
- Removal requests: open an issue on this Actor's Issues tab naming the person, email address or domain to remove. It is added to our suppression list and honoured within 7 days; from then on matching records are not returned.
- Only boards that publish their feed for reuse are read; each job carries its attribution line.

### Limits (stated honestly)

- Coverage is what the boards publish: Remote OK's API gives its ~100 newest jobs and We Work Remotely's feeds their newest jobs per category. By default each board returns up to 100 jobs; set 'Max results per source' to 0 for everything.
- Categories are normalised from titles and board categories by keyword rules; unusual titles can land in 'other'.
- Locations are free text from the boards; region matching is by word, synonym and country code, not geography (e.g. 'Americas' does not match 'USA', 'Europe' does not match a list of European countries).
- Jobicy, Remotive, Himalayas, Working Nomads and Arbeitnow are excluded on purpose (their terms forbid this reuse).
- Apply links go to the job page on the source board, as the boards require, not to the employer's form.
- If one board is down or rate-limits the run, the other board's jobs are still returned and the status says which board failed.

### Works great with

- **Then: [Multiple Job Boards Scraper](https://apify.com/aurelix/multi-job-board-scraper)**: run the same role across LinkedIn and about 50 company career sites in one deduplicated list

### Related Aurelix tools

Public Aurelix Actors, grouped by the data they collect. All are pay-per-result and need no login.

#### Jobs and hiring data

- **[Greenhouse Jobs Scraper](https://apify.com/aurelix/greenhouse-jobs-scraper)**: Live jobs from a company's Greenhouse, Lever, Ashby or SmartRecruiters board, with salary and Canadian province tags.
- **[LinkedIn Jobs Country Filter Scraper](https://apify.com/aurelix/linkedin-jobs)**: Public LinkedIn job postings by keyword and country: title, company, location, seniority, job type, salary text, description.
- **[Multiple Job Boards Scraper](https://apify.com/aurelix/multi-job-board-scraper)**: LinkedIn, about 50 company career sites, Remote OK and We Work Remotely jobs in one deduplicated list.

#### E-commerce and product data

- **[AliExpress Scraper API](https://apify.com/aurelix/aliexpress-product-search)**: AliExpress search results by keyword: price, discount, rating, units sold, ship-from country and sponsored flag.
- **[Amazon New Releases & Best Sellers](https://apify.com/aurelix/amazon-best-sellers)**: Amazon Best Sellers and New Releases top 100 on 10 marketplaces: rank, ASIN, price, rating, rank change.
- **[Shopify Product Export Scraper](https://apify.com/aurelix/shopify-products-scraper)**: Every public product of any Shopify store with variants, SKUs, prices, barcodes, stock counts and collections.

#### Leads and company data

- **[Decision Maker Finder](https://apify.com/aurelix/decision-maker-finder)**: Founders, CEOs, VPs and department heads from company team pages, with title, seniority and function.
- **[Newly Funded Companies Hiring](https://apify.com/aurelix/funded-companies-hiring)**: Companies that just raised money (SEC Form D), with their open roles and business contacts, as a new-only monitor.
- **[Google Maps Phone Scraper](https://apify.com/aurelix/google-maps-scraper)**: Local business lists from Google Maps: phones, websites, ratings, hours, coordinates; optional website emails and socials.
- **[Recently Funded Companies API](https://apify.com/aurelix/recently-funded-companies)**: US companies that just filed an SEC Form D: amount raised, industry, state, executives, confirmed website.
- **[Tech Stack API](https://apify.com/aurelix/tech-stack-detector)**: CMS, e-commerce platform, analytics, ad pixels, chat, CDN and email provider for each domain you enter.

#### Ad intelligence

- **[Competitor Watch](https://apify.com/aurelix/competitor-watch)**: One report per competitor with only what is new: Meta and TikTok ads, page changes, Shopify products and prices, jobs.
- **[Facebook Ad Library Search & API](https://apify.com/aurelix/facebook-ad-library-scraper)**: Facebook and Instagram business ads from the Meta Ad Library: copy, creatives, landing pages, dates, optional EU reach.

#### Canada and government data

- **[Canada Building Permits](https://apify.com/aurelix/canada-building-permits-scraper)**: Building permits and development applications from 7 Canadian cities: address, type, status, dates, value, applicant, contractor and Toronto planner contact.

#### AI, content and SEO

- **[Google Trends by Region](https://apify.com/aurelix/google-trends-scraper)**: Google Trends interest over time, by region and rising queries for any number of keywords, plus trending searches.
- **[Google Autocomplete API](https://apify.com/aurelix/google-autocomplete-scraper)**: Expands seed keywords into hundreds of real Google and YouTube autocomplete phrases, tagged by search intent.
- **[PDF Table Extraction & PDF to Markdown OCR](https://apify.com/aurelix/pdf-to-markdown)**: Turns linked PDF and Word files into Markdown per page, with tables as JSON rows, RAG chunks and OCR.
- **[Broken Link Crawler & SEO Audit](https://apify.com/aurelix/seo-audit-crawler)**: Audits a whole site: one row per page with SEO checks and broken links, plus a ranked issues summary.
- **[Website to Markdown API](https://apify.com/aurelix/website-to-markdown)**: Crawls a site and returns one row of clean main-content Markdown per page, with title, headings and links.
- **[YouTube Transcript Scraper](https://apify.com/aurelix/youtube-transcript-scraper)**: Returns YouTube video transcripts as text, timed segments and AI chunks, from videos, channels, playlists or searches.

#### More data tools

- **[Tennis Betting Odds Scraper](https://apify.com/aurelix/tennis-odds-scraper)**: Tennis results and upcoming matches with opening and closing odds per bookmaker and implied probabilities.

### Recent changes

- **0.1**: Accepts other remote job scrapers' input fields (searchQueries, platforms, countries, maxItems and more), keywords and regions pasted as one comma list, country codes such as US or GB, and a minimum salary written as '80k'; when both boards are down the run ends with nothing charged instead of failing.

The full history is on the **Changelog** tab.

### Tested daily

An automated health check runs this Actor every day on a fixed input and checks that at least 7 jobs come back with `job_id`, `source`, `title`, `job_url`, `attribution`, `posted_at` filled in; a failed check alerts the maintainer straight away.

### Your feedback

Missing a field, found a bug or need another filter? Open an issue on the **Issues** tab; we aim to answer within a day. If this Actor saved you time, a short review helps other people find it.

# Changelog

This Actor's version history is a separate document: https://apify.com/aurelix/remote-jobs-scraper/changelog.md

# Actor input Schema

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

Job boards to read: 'remoteok' (Remote OK), 'weworkremotely' (We Work Remotely). Default = both.

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

Keep jobs whose title or company contains at least one of these words (case-insensitive), e.g. \['python', 'data engineer']. One per line or comma-separated. Empty = all jobs.

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

Keep jobs in these normalised categories, e.g. \['software-development', 'data-ai']. Empty = all categories.

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

Keep jobs whose allowed location mentions one of these words, e.g. \['USA', 'Canada', 'Europe', 'UTC']. Country names or two-letter codes (US, GB, DE) work; matching is case-insensitive on the published location text. Empty = all locations.

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

When filtering by region, also keep jobs open to anyone anywhere ('Worldwide', 'Anywhere').

## `employmentTypes` (type: `array`):

Keep only these employment types, e.g. \['FULL_TIME', 'CONTRACT']. Empty = all types.

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

Keep only jobs that publish a salary whose top of range, converted to yearly, is at least this amount in the posting's currency, e.g. 80000. Jobs without a published salary are dropped when this is set. 0 = no salary filter.

## `maxResultsPerSource` (type: `integer`):

Upper limit of jobs returned per source after filters, newest first, e.g. 50. Default 100. 0 = everything the boards publish (several hundred jobs).

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

Include the job description as plain text and HTML. Turn off for smaller output.

## `incremental` (type: `boolean`):

Return only jobs not returned by a previous run with the same sources and filters. Duplicates across boards count once. Use with a schedule for a daily feed.

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

Name for the 'new since last run' memory, e.g. 'python-jobs-daily'. Leave empty to derive it from the sources and filters.

## `slackWebhookUrl` (type: `string`):

After each run, post a short digest to Slack: how many results were saved (new ones only when 'Only new jobs since last run' is on) and the top 10 with links, e.g. https://hooks.slack.com/services/T000/B000/XXXX. Nothing is posted when the run saved nothing. Leave empty to skip.

## `webhookUrl` (type: `string`):

After each run, POST the same digest as JSON (actor, newOnly, count, items = top 10 results, runUrl, text) to any URL, e.g. a Zapier, Make or n8n webhook. Nothing is sent when the run saved nothing. Leave empty to skip.

## Actor input object example

```json
{
  "sources": [
    "remoteok",
    "weworkremotely"
  ],
  "keywords": [
    "python"
  ],
  "categories": [],
  "regions": [],
  "includeWorldwide": true,
  "employmentTypes": [],
  "minSalary": 0,
  "maxResultsPerSource": 10,
  "includeDescription": true,
  "incremental": false
}
```

# Actor output Schema

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

All remote job postings found in this run, one item per job, 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 = {
    "keywords": [
        "python"
    ],
    "maxResultsPerSource": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("aurelix/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 = {
    "keywords": ["python"],
    "maxResultsPerSource": 10,
}

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

```

## MCP server setup

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