# Remote Jobs API: Remote OK, We Work Remotely & Jobicy (`atarivo/remote-jobs-api-remoteok-weworkremotely-jobicy`) Actor

Fresh remote jobs from Remote OK, We Work Remotely and Jobicy in one schema: title, company, remote region, category, salary, tags, posted date, apply link and each board's attribution. Keyword and date filters, dedup across boards. Public feeds only, no login.

- **URL**: https://apify.com/atarivo/remote-jobs-api-remoteok-weworkremotely-jobicy.md
- **Developed by:** [Atarivo Enterprises Inc.](https://apify.com/atarivo) (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 $2.00 / 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 API: Remote OK, We Work Remotely & Jobicy returns fresh remote jobs from three
public remote-job boards as clean rows in one schema: title, company, remote region, category,
salary, tags, posted date, apply link, and the board's attribution and link-back URL on every
row. It is built for remote-job newsletters, job boards, recruiters, labour-market researchers
and AI agents that want remote openings without writing three parsers. To try it, keep the
sample input and press **Start**: it reads 10 jobs from each board in a few seconds.

### What does the Remote Jobs API do?

- Returns **one dataset row per remote job** from **Remote OK**, **We Work Remotely** and
  **Jobicy**, in one normalised schema. The columns match our ATS Jobs APIs (`ats` becomes
  `source`), so the tables merge.
- **Credits every board in the row**: `attribution` names the board and `source_url` is the
  job's page on it. Each board asks for a link back and a credit wherever its jobs are shown;
  the data is ready for that, and you must keep it.
- Optional **keyword filter** (`query`: every word must appear in the title or tags) and
  **date filter** (`postedSinceDays`).
- **Removes duplicates**: within a run by `dedup_key` (`source:job_id`), and across boards when
  the same company posts the same title on two of them (kept from the board listed first).
  Duplicates are never charged.
- Adds **salary** where the board publishes it (Remote OK and Jobicy), **tags** (Remote OK tags,
  We Work Remotely skills) and the **remote region** (e.g. `USA Only`, `Europe`, `Worldwide`).
- Calls **only the boards' public feeds** (`remoteok.com`, `weworkremotely.com`,
  `jobicy.com`). It sends an honest User-Agent that names this Actor, reads and obeys each
  host's robots.txt (wildcards and `Crawl-delay` included), sends at most 2 requests per second
  per host, never follows a redirect and retries a failed request once.
- **No login, no cookies, no proxies, no personal data.** It reads job postings the boards
  publish for anyone to reuse.
- **Remotive, Himalayas and Arbeitnow are not included**, on their own terms (see the FAQ).

### How to use the Remote Jobs API

1. Pick the **Job boards** (all three by default).
2. Optionally type a **Keyword**, set **Posted in the last N days**, tick **Include the job
   description text**, and set **Max jobs per board** (default 500).
3. Press **Start**. Open the **Output** tab for the jobs table, or read the dataset through the
   API in JSON, CSV or Excel. The `RUN_SUMMARY` record in the key-value store says, per board,
   how many jobs were read, filtered out, skipped as duplicates and delivered.

Calling it from an AI agent: `{"sources": ["weworkremotely", "jobicy"], "query": "python",
"postedSinceDays": 7}`. The description above is also the Actor's tool description in the
Apify MCP server.

Schedule it **no more often than once an hour** (Jobicy asks for that; the boards change a few
times a day) and compare `dedup_key` values between runs to see which jobs are new.

### Pricing

| Event | What you pay for | Price |
|---|---|---|
| `job-scraped` | One remote job returned as a row | $0.0020 |

Each run also has a start fee of $0.001. A board that did not answer, that robots.txt told us
not to read, or that returned something we could not read gives one error row that is **never
charged**. Duplicates are never charged. Set **Max cost per run** to cap a run; the Actor stops
cleanly at the cap and says so in its status message. Platform usage is included (no "+usage"
charges).

### Input

| Field | Type | Required | Notes |
|---|---|---|---|
| `sources` | array of strings | no | Any of `remoteok`, `weworkremotely`, `jobicy`; default all three. Remotive, Himalayas and Arbeitnow are refused with the reason. |
| `query` | string | no | Up to 100 characters. Every word must appear in the title or tags. Also sent to Jobicy's title search. |
| `maxJobsPerSource` | integer | no | 1 to 5,000; default 500. Caps the jobs (and the cost) per board. |
| `includeDescription` | boolean | no | Default `false`. Adds `description_text`. Same price. |
| `postedSinceDays` | integer | no | 1 to 90. Jobs without a posted date are left out when set. |

```json
{
  "sources": ["remoteok", "weworkremotely", "jobicy"],
  "maxJobsPerSource": 10,
  "includeDescription": false
}
```

### Output

One row per job:

```json
{
  "title": "Senior Backend Engineer",
  "company": "Example Corp",
  "location": "USA",
  "remote": true,
  "remote_region": "USA",
  "department": "Software Engineering",
  "posted_at": "2026-10-30T16:00:00Z",
  "apply_url": "https://jobicy.com/jobs/100001-senior-backend-engineer",
  "source": "jobicy",
  "job_id": "100001",
  "dedup_key": "jobicy:100001",
  "source_url": "https://jobicy.com/jobs/100001-senior-backend-engineer",
  "attribution": "Jobicy",
  "salary_min": 120000,
  "salary_max": 160000,
  "salary_currency": "USD",
  "salary_period": "yearly",
  "tags": []
}
```

`apply_url` is the job's page on the board, unchanged: the boards ask that apply buttons lead
there. `remote` is always `true`. `salary_*` are `null` when the board gives no salary; Remote
OK gives figures without a currency field, so `salary_currency` is `null` there. A board that
failed gives one row with `error`, `message`, `tried` and `charged: false` instead. Run storage
is kept for your plan's data-retention period, then deleted by Apify.

| Board | Feed read | What it publishes | Credit line it asks for |
|---|---|---|---|
| Remote OK | `GET https://remoteok.com/api` | about 100 latest jobs, salary, tags | link to the job on Remote OK, name "Remote OK" |
| We Work Remotely | `GET https://weworkremotely.com/remote-jobs.rss` and its category feeds | latest jobs per category, region, skills | link back to We Work Remotely |
| Jobicy | `GET https://jobicy.com/api/jobs` (cursor pages) | jobs of the last 7 days, salary, industry | credit Jobicy and link to the source |

### Other Actors by Atarivo

Every Atarivo Actor follows the same rules: limited permissions, no "+usage" pricing, charges
only after results are saved, and at least one result row per run.

- **[ATS Jobs API: Greenhouse, Lever & Ashby](https://apify.com/atarivo/ats-jobs-api-greenhouse-lever-ashby)**: every open job on the Greenhouse, Lever and Ashby boards you list, in the same row schema, at the same price.
- **[Workable, Recruitee, Personio & Teamtailor Jobs API](https://apify.com/atarivo/ats-jobs-api-workable-recruitee-personio-teamtailor)**: the same rows from Workable, Recruitee, Personio and Teamtailor career sites. With the two ATS APIs you can read jobs straight from employers' career sites.
- **[PDF, Image & Word to Text and Markdown (OCR)](https://apify.com/atarivo/pdf-image-text-markdown-extractor)**: returns the text, Markdown, tables and page facts of a PDF, PNG, JPEG, TIFF or Word .docx file, one dataset row per page, plus RAG chunks with page spans. OCR runs only on scanned or unreadable pages. First page free.

### FAQ, disclaimers and support

**Is it legal?** It reads only the public feeds each board publishes for reuse, honours each
host's robots.txt and rate limits, and carries each board's attribution in every row. What
each board says (all read on 2026-10-31):

- **Remote OK** (`GET https://remoteok.com/api`). The API's own legal notice: "Please link
  back (with follow, and without nofollow!) to the URL on Remote OK and mention Remote OK as a
  source, so we get traffic back from your site. If you do not we'll have to suspend API
  access." Its terms: "You agree to link back with a web hyperlink or in-app hyperlink to our
  site on the page or app screen where you use the data from our APIs or site." robots.txt:
  `Allow: /`, `Crawl-delay: 1` (honoured), content signal `ai-train=no`.
- **We Work Remotely** (`GET https://weworkremotely.com/remote-jobs.rss` and the category
  feeds it lists). Its RSS page: "Anyone can use the feed, all we ask is that you attribute the
  links back to We Work Remotely." robots.txt: `Allow: /`.
- **Jobicy** (`GET https://jobicy.com/api/jobs`). Its API docs: "Clearly credit Jobicy as the
  original source when displaying listings", "Apply links provided by our free API must
  continue to direct users to the original job pages on Jobicy", "Our free Jobs API can be
  used in commercial projects ... No separate commercial agreement or approval is required",
  "You can store, cache, process, and redistribute job data as needed", and "Start a new
  automated pass no more than once per hour". robots.txt does not disallow `/api/`.

**Your part:** wherever you show these jobs, link each one to its `source_url` with a normal
(followed) link and name the board from `attribution`; keep `apply_url` unchanged; do not use
the boards' logos; do not present the jobs as your own postings; do not train AI models on
Remote OK rows (`ai-train=no`). You are responsible for how you use the data.

**Why no Remotive, Himalayas or Arbeitnow?** Remotive's robots.txt disallows `/api/*` for every
crawler, and its API terms say "Please do not submit Remotive jobs to third Party websites".
Himalayas' API terms say "Show the jobs only on sites and apps you operate. Do not pass them on
to third parties, such as other job boards, aggregators". Arbeitnow's terms grant its materials
"for personal, non-commercial transitory viewing only" and it sells commercial access as a
private API. An Actor passes jobs on to you, so we follow all three.

**Why do I get fewer jobs than I asked for?** Each board publishes a limited window: Remote OK
about 100 latest jobs, We Work Remotely the latest jobs per category feed, Jobicy the last 7
days (with a 3-hour delay). `maxJobsPerSource` is a ceiling, not a promise.

**Is it affiliated with Remote OK, We Work Remotely or Jobicy?** No. The names describe the
data source only.

**Something is wrong.** Open an issue on the **Issues** tab with the run ID. Issues are
answered within 14 days.

This Actor is provided as is, under Apify's Standard Actor Contract. It is not affiliated with
or endorsed by Remote OK, We Work Remotely or Jobicy.

# Actor input Schema

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

Which boards to read: remoteok (Remote OK), weworkremotely (We Work Remotely) and jobicy (Jobicy). Default: all three. A job posted on two boards is returned once, from the board listed first. Remotive, Himalayas and Arbeitnow are refused (their terms do not allow passing their jobs on).

## `query` (type: `string`):

Keep only jobs whose title or tags contain every word you type (case-insensitive), e.g. python or data engineer. Up to 100 characters. Also sent to Jobicy's own title search. Leave empty for every job.

## `maxJobsPerSource` (type: `integer`):

Stop reading a board after this many matching jobs. From 1 to 5000; default 500. Each job is one charged event, so this also caps the cost per board. Remote OK publishes about 100 jobs, We Work Remotely a few hundred, Jobicy the last 7 days.

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

Add description_text (the posting as plain text) to every row. Off by default: rows stay small. The price per job is the same either way.

## `postedSinceDays` (type: `integer`):

Keep only jobs posted in the last N days, from 1 to 90. Jobs without a posted date are left out when this is set. Leave empty for every job the boards publish.

## Actor input object example

```json
{
  "sources": [
    "remoteok",
    "weworkremotely",
    "jobicy"
  ],
  "maxJobsPerSource": 10,
  "includeDescription": false
}
```

# Actor output Schema

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

One row per remote job (title, company, location, remote_region, department, posted_at, apply_url, source, job_id, dedup_key, source_url, attribution, salary_min, salary_max, salary_currency, salary_period, tags; description_text when includeDescription is on), plus one uncharged row with error, message and tried per board that could not be read.

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

Per board: the outcome, the requests made, and the number of jobs read, filtered out, skipped as duplicates and delivered.

# 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",
        "weworkremotely",
        "jobicy"
    ],
    "maxJobsPerSource": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("atarivo/remote-jobs-api-remoteok-weworkremotely-jobicy").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",
        "weworkremotely",
        "jobicy",
    ],
    "maxJobsPerSource": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("atarivo/remote-jobs-api-remoteok-weworkremotely-jobicy").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",
    "weworkremotely",
    "jobicy"
  ],
  "maxJobsPerSource": 10
}' |
apify call atarivo/remote-jobs-api-remoteok-weworkremotely-jobicy --silent --output-dataset

```

## MCP server setup

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

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/2zrNbSzXBL3J6mfrr/builds/CAZi3gNvJZ0iemjYh/openapi.json
