# RemoteOK Jobs Scraper — Remote Jobs by Tag with Salaries (`fabrikit/remoteok-jobs-scraper`) Actor

Remote OK jobs scraper: remote job listings from remoteok.com's public JSON feed with tags, salary ranges, locations, posting dates and plain-text descriptions. Filter by tag, keyword, location, minimum salary and date. No API key, no login. From US$0.90 per 1,000 jobs.

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

## Pricing

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

## RemoteOK Jobs Scraper — Remote Jobs by Tag with Salaries

RemoteOK Jobs Scraper extracts remote job listings from remoteok.com — title, company, tags, salary range, location, posting date and the full description — as clean JSON, CSV or Excel. Pick Remote OK tags such as `dev`, `python`, `marketing` or `customer support`, then narrow by keyword, location, minimum salary and date. No API key, no login, no browser.

**Pricing: US$0.90 per 1,000 jobs**, platform usage included.

This Actor covers one site. If you want Remote OK together with We Work Remotely, Remotive, Himalayas, Jobicy and Arbeitnow in one normalized dataset, use the multi-source [Remote Jobs Aggregator](https://apify.com/fabrikit/remote-jobs-aggregator). Its other single-site sibling is the [We Work Remotely Scraper](https://apify.com/fabrikit/weworkremotely-scraper).

### What you get

One record per unique job:

- `title`, `company`, `location` (free text as the employer wrote it: *Worldwide*, *United States*, *Remote - US*…; left blank by some employers)
- `tags` — Remote OK's skill, role and seniority tags (`dev`, `react`, `senior`, `non tech`…)
- `salaryMin`, `salaryMax`, `salaryCurrency` — the advertised range in US dollars per year, as published by Remote OK (a minority of listings have one: 5–20 % in our test runs)
- `description` — plain text with HTML removed; Remote OK's anti-spam footer and personal contact details are stripped. `descriptionTruncated` tells you when Remote OK only publishes an excerpt of an aggregated listing
- `postedAt` (ISO 8601), `url` and `applyUrl` on remoteok.com, `slug`, `isVerified` and `isOriginal` flags, `companyLogo` (null while the feed leaves it empty), `source: "remoteok"`, `scrapedAt`

### Use cases

- Feed a remote-jobs board, newsletter or Slack/Discord alert with new Remote OK postings every hour
- Track which skills, seniorities and salary bands remote employers are hiring for
- Build lead lists of companies hiring remotely in your niche (`tags: ["sales"]`, `keywords: ["fintech"]`)
- Compare published remote salaries by tag over time
- Give an AI agent a cheap, structured source of remote jobs

### How to use

Newest 50 remote jobs of any kind (the default input):

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

Newest Python and JavaScript developer jobs, with a published salary of at least US$100k:

```json
{ "tags": ["python", "javascript"], "minSalary": 100000, "maxItems": 200 }
```

Marketing and customer-support jobs posted in the last 7 days that mention "SaaS", open to the whole world:

```json
{
  "tags": ["marketing", "customer support"],
  "keywords": ["saas"],
  "searchDescription": true,
  "locations": ["Worldwide", "Anywhere"],
  "postedWithinDays": 7,
  "maxItems": 100
}
```

Jobs tagged both `dev` and `python`, without descriptions:

```json
{ "tags": ["dev+python"], "includeDescription": false, "maxItems": 100 }
```

#### Input fields

| Field | What it does |
|---|---|
| `tags` | Remote OK tags, one feed each (`dev`, `design`, `exec`, `customer support`…). `dev+python` requires both tags. Empty = general feed |
| `keywords`, `excludeKeywords` | Keep or skip jobs whose title, company or tags contain a word; `searchDescription: true` also searches the description |
| `locations` | Keep jobs whose location text contains one of the values; listings without a location are skipped |
| `minSalary` | Keep jobs whose advertised range reaches this amount (USD per year); listings without a salary are skipped |
| `onlyWithSalary` | Skip listings without a salary range |
| `postedWithinDays` | Only jobs posted in the last N days |
| `includeDescription` | Plain-text description on every item (default on; no extra requests) |
| `maxItems` | Exact number of unique jobs to return (default 50) |
| `proxyConfiguration` | Requests go out directly first; the Actor climbs to Apify datacenter and residential proxies only if Remote OK blocks |

Each Remote OK feed holds the ~100 newest jobs and the API has no paging. When you ask for more than the general feed holds and give no tags, the Actor walks 50+ popular tag feeds and removes duplicates, so a run can reach several hundred unique jobs; with tags it reads exactly the feeds you asked for.

### Output example

```json
{
  "id": "1137537",
  "url": "https://remoteok.com/remote-jobs/remote-head-of-technology-sanctuary-computer-1137537",
  "title": "Head of Technology",
  "company": "Sanctuary Computer",
  "companyLogo": null,
  "location": null,
  "tags": ["exec", "technical", "engineer", "senior", "dev"],
  "salaryMin": 140000,
  "salaryMax": 250000,
  "salaryCurrency": "USD",
  "description": "We're the software team behind ... (plain text)",
  "descriptionTruncated": false,
  "postedAt": "2026-10-16T22:00:03.000Z",
  "applyUrl": "https://remoteok.com/remote-jobs/remote-head-of-technology-sanctuary-computer-1137537",
  "slug": "remote-head-of-technology-sanctuary-computer-1137537",
  "isVerified": false,
  "isOriginal": true,
  "source": "remoteok",
  "scrapedAt": "2026-10-20T13:05:41.512Z"
}
```

The run also stores a `SUMMARY` record in the key-value store: feeds read, jobs seen, jobs filtered out, duplicates skipped, empty feeds (a sign of a misspelled tag), the feed's `last_updated` time and the proxy rung used.

### Pricing

| Event | Price |
|---|---|
| `job-result` — one unique job saved to the dataset | US$0.90 per 1,000 |

Examples: 100 jobs = US$0.09; 1,000 jobs = US$0.90; a daily 200-job pull for a month ≈ US$5.40. Filtered-out jobs and duplicates are never charged. Compute and proxy are included.

### How it compares

- **Remote Jobs Aggregator (fabrikit)** — the multi-source version: six remote job boards in one schema, de-duplicated by company and title. Choose it when you want coverage; choose this Actor when you only need Remote OK and want the lowest price per job.
- **General remote-jobs aggregators on the Store** typically bill US$1.99 to US$3.00 per 1,000 for the same Remote OK listings mixed with other sources.
- **Other Remote OK scrapers** usually return the raw API objects (HTML descriptions, `0` for missing salaries, mangled accents). This one returns plain text, real `null`s, ISO dates, fixed character encoding and exact `maxItems`, and removes the anti-spam footer Remote OK appends to every description.

### Integrations

Run it from the Apify API or the JavaScript/Python clients, schedule it, and push results to Google Sheets, Airtable, Slack, webhooks, n8n, Make or Zapier through Apify integrations. The Actor works as a tool in the Apify MCP server, so AI agents can call it ("find remote Python jobs over US$120k posted this week").

### Attribution and legal

Remote OK's API terms ask anyone reusing the data to link back to the job page on Remote OK with a normal (follow) link and to name **Remote OK** as the source; the Remote OK logo is a registered trademark and may not be used without written permission. Every item carries the `url` for that link. This Actor is not affiliated with Remote OK. Listings are public job ads; e-mail addresses and phone numbers of individual people found in descriptions are removed, company role mailboxes (jobs@, careers@) are kept. Use the data in line with Remote OK's terms and the laws that apply to you.

### FAQ

**Can I get more than ~100 jobs per tag?** No — Remote OK's feed exposes only the newest ~100 listings per tag and has no paging. Use several tags, or schedule the Actor (hourly or daily) and let your dataset grow over time.

**Why is `location` sometimes empty?** Remote OK does not require it; in our test runs between 15 % and 50 % of the listings had no location, depending on the feed. Those listings are skipped when `locations` is set.

**Are salaries reliable?** They are what the employer typed in: USD per year for most listings, but a few enter hourly or monthly figures. The Actor passes the numbers through unchanged and sets `salaryCurrency` to `USD` as Remote OK does.

**Do I need a proxy?** Normally not. Remote OK serves the feed to direct requests; the built-in ladder only switches to Apify proxies if a block is seen.

**What does an empty result mean?** Either an unknown tag (check the spelling at `remoteok.com/remote-<tag>-jobs`) or filters that nothing matched; the status message and `SUMMARY` say which.

**Does it include the logo?** The field exists, but the feed currently sends it empty for every listing, so it is `null`.

### Changelog

- **0.1** (October 2026) — first release: general and tag feeds, combined tags, keyword/location/salary/date filters, plain-text descriptions, encoding fix, exact `maxItems`, pay-per-result pricing.

***

### En español

Scraper de **empleos remotos de Remote OK** (remoteok.com): título, empresa, etiquetas, rango salarial en USD, ubicación, fecha y descripción en texto plano. Filtra por etiqueta (`dev`, `python`, `marketing`…), palabra clave, ubicación, salario mínimo y fecha. Sin API key ni login. **US$0,90 por 1.000 empleos**. Si necesitas varias bolsas remotas a la vez, usa el [Remote Jobs Aggregator](https://apify.com/fabrikit/remote-jobs-aggregator). Al reutilizar los datos, Remote OK pide enlazar a la oferta original y nombrarlo como fuente.

# Actor input Schema

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

One Remote OK tag per entry, as used in remoteok.com/remote-<tag>-jobs URLs: for example dev, python, javascript, react, design, marketing, sales, customer support, exec, finance, medical, non tech. Each tag returns its ~100 newest jobs. Combine tags with a plus sign to require all of them (dev+python). Leave empty for the general feed (newest jobs of any tag).

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

Keep only jobs whose title, company or tags contain one of these words (case-insensitive). Turn on 'Search in description' to also match the description text.

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

Skip jobs whose title, company or tags (and description, if 'Search in description' is on) contain one of these words.

## `searchDescription` (type: `boolean`):

Match keywords and exclude keywords against the full description too, not only title, company and tags.

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

Keep only jobs whose location text contains one of these values, for example Worldwide, United States, Europe, Remote - US, Canada. Remote OK's location is free text and some employers leave it blank; those listings are skipped when this filter is set.

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

Keep only jobs whose advertised salary range reaches at least this amount, in US dollars per year as published by Remote OK. Jobs without a salary are skipped when this is set.

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

Skip jobs that do not advertise a salary range. Only a minority of Remote OK listings publish one, so combine with several tags or a higher maxItems.

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

Keep only jobs posted in the last N days. 0 = any date.

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

Add the job description as plain text (HTML removed, Remote OK's anti-spam footer and personal contact details stripped). It is part of the feed, so it costs no extra requests; turn off for a lighter dataset.

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

Stop after this many unique jobs. Each Remote OK feed holds about 100 jobs; when no tags are given and more are needed, the Actor walks popular tag feeds and removes duplicates.

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

Requests go out directly first (Remote OK is a public JSON feed). If Remote OK blocks them, the Actor climbs to Apify datacenter and then residential proxies on its own. Leave the default.

## Actor input object example

```json
{
  "searchDescription": false,
  "onlyWithSalary": false,
  "postedWithinDays": 0,
  "includeDescription": true,
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

All Remote OK jobs collected during the run (one record per unique job)

# 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 = {
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("fabrikit/remoteok-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 = {
    "maxItems": 50,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("fabrikit/remoteok-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 '{
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call fabrikit/remoteok-jobs-scraper --silent --output-dataset

```

## MCP server setup

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