# Remote OK Scraper (`scraptivo/remoteok-scraper`) Actor

Collects remote job listings from Remote OK using search queries, listing URLs, or role, location, and salary filters. Returns title, company, salary, tags, and apply links.

- **URL**: https://apify.com/scraptivo/remoteok-scraper.md
- **Developed by:** [Scraptivo](https://apify.com/scraptivo) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.97 / 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.
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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

**Remote OK Scraper** collects remote job listings from [Remote OK](https://remoteok.com) and turns them into structured data for recruiting, salary research, and job-board feeds. Provide a search query or a Remote OK URL, run the Actor, and export title, company, salary, tags, benefits, and apply links to JSON, CSV, Excel, or your preferred integration. Use it to monitor new roles, benchmark pay, and automate recurring collection. Pricing starts at **$1.00 per 1,000 jobs**, with optional job details at **$1.00 per 1,000**.

### What can you automate with Remote OK Scraper?

- **Build a remote-jobs database** — Collect listings filtered by keyword, role tag, location, benefits, or minimum salary.
- **Capture apply links** — Export the job URL and apply URL with company, tags, and posting date.
- **Benchmark pay** — Collect `salaryMin` and `salaryMax` when Remote OK publishes a range.
- **Enrich selected jobs** — Turn on job details for the full description and richer apply fields.
- **Sort the board** — Use latest, highest paid, most viewed, most applied, hottest, or most benefits.
- **Schedule recurring scans** — Re-run the same query daily and merge on job `id`.

### Who is this scraper for?

| Team | Workflow |
|---|---|
| Recruiters and sourcers | Building lead lists of open remote roles by tag and location. |
| Compensation teams | Collecting published salary bands for benchmarking. |
| Job-board operators | Feeding structured listings into a site or ATS. |
| Researchers | Tracking remote hiring volume by role and region. |

### What data can you collect from Remote OK?

| Data group | Example fields | How it helps |
|---|---|---|
| Job identity | `id`, `position`, `url` | Deduplicate and reopen the posting. |
| Employer | `company`, `companyUrl`, `companyLogo` | Identify who is hiring. |
| Compensation | `salaryMin`, `salaryMax`, currency, period | Compare pay when published. |
| Fit | `location`, `tags`, `benefits`, `employmentType` | Filter by skill, perk, and region. |
| Apply | `applyUrl`, `datePosted`, `isVerified` | Send candidates or track freshness. |
| Details | Full description | Appears when **Scrape job details** is enabled. |

Card-level title, company, URL, tags, and location are returned on every job. Full description is added when job details are enabled.

### How to use Remote OK Scraper

1. Open the [Remote OK Scraper](https://apify.com/scraptivo/remoteok-scraper) on Apify.
2. Enter search queries such as `python`, or paste Remote OK listing or job URLs.
3. Optionally set tags, locations, benefits, `minSalary`, sort order, and a `maxItems` limit.
4. Run the Actor and wait for job records to appear in the dataset.
5. Export JSON, CSV, or Excel, or connect the dataset to your workflow.

```json
{
    "searchQueries": ["python"],
    "sortBy": "date",
    "maxItems": 10,
    "scrapeJobDetails": false,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": ["RESIDENTIAL"]
    }
}
```

### Example workflow

#### Watch new Python remote jobs every weekday

1. Schedule a daily run with `searchQueries` = `["python"]` and `sortBy` = `date`.
2. Keep `scrapeJobDetails` off for a cheap card-level snapshot, then enable it for roles you want to read.
3. Send new records to Google Sheets or Slack through a webhook.
4. Deduplicate user-side against the stable job `id`.

### Automate and integrate your results

- **Schedules** — Remote OK turns over quickly. Run **daily** for sourcing and **weekly** for salary research.
- **Webhooks** — Push completed datasets into Sheets, Slack, or an ATS.
- **Exports and API** — Download from the Apify Console or start a run from the API:

```shell
curl "https://api.apify.com/v2/acts/scraptivo~remoteok-scraper/runs?token=YOUR-APIFY-TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "searchQueries": ["python"],
    "sortBy": "date",
    "maxItems": 10,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": ["RESIDENTIAL"]
    }
  }'
```

- **Deduplication** — The Actor appends results on every run. Use `id` as the stable key.

### Input reference

| Field | Type | Required | Default | What it controls |
|---|---|---:|---|---|
| `startUrls` | Array of URLs | No | — | Remote OK listing or job URLs. When set, filter fields below are ignored for those URLs. |
| `searchQueries` | Array of strings | No | — | Free-text searches. Each query is scraped separately. |
| `tags` | Array of strings | No | — | Role/category tags from the schema (for example `dev`, `backend`, `python`). Combined with AND. |
| `locations` | Array of strings | No | — | Countries or regions (for example `Worldwide`, `US`, `region_EU`). Each location is a separate search. |
| `benefits` | Array of strings | No | — | Required benefits such as `401k`, `async`, `4_day_workweek`. |
| `minSalary` | Integer | No | `0` | Minimum annual salary in USD (0–250000). Ignored when Start URLs are set. |
| `sortBy` | String | No | `date` | `date`, `salary`, `views`, `applied`, `hot`, or `benefits`. |
| `maxItems` | Integer | No | `0` | Maximum jobs (`0` = unlimited). |
| `scrapeJobDetails` | Boolean | No | `false` | Fetch each job page for description and richer apply fields. Charges `job-details`. |
| `proxyConfiguration` | Proxy object | No | Apify proxy, RESIDENTIAL | Residential proxies are recommended. |

#### Do Start URLs override filters?

Yes. When `startUrls` is provided, tags, locations, benefits, search queries, and `minSalary` are ignored for those URLs. `sortBy` still applies if the URL does not already include `order_by`.

### Output example

Each dataset item is one job:

```json
{
    "id": "1137062",
    "position": "DESARROLLADOR FULL STACK",
    "company": "Kruger NearShore LLC - Rekluti",
    "url": "https://remoteok.com/remote-jobs/remote-desarrollador-full-stack-kruger-nearshore-llc-rekluti-1137062",
    "applyUrl": "https://remoteok.com/l/1137062",
    "location": "Probably worldwide",
    "tags": ["Full Stack", "Front End", "Python", "Developer", "Testing"],
    "benefits": [],
    "employmentType": "FULL_TIME",
    "datePosted": "2026-08-22T00:00:12+00:00",
    "isVerified": false,
    "sourceQuery": "python",
    "detailsFetched": false
}
```

### How much does it cost to scrape Remote OK?

The Actor uses pay-per-event pricing plus a small Actor-start event ($0.00005 per start, scaled by memory):

- **$1.00 / 1,000 jobs** — a `job` event for every listing written to the dataset.
- **$1.00 / 1,000 job details** — a `job-details` event only when **Scrape job details** is enabled.

A listing-only run of 1,000 jobs costs **$1.00**. Enriching the same 1,000 jobs with details costs **$2.00**. Volume discounts on Apify paid plans reduce the per-1,000 rate (for example **$0.97 per 1,000** at the Gold plan). Compute units consumed are deducted from your Apify plan.

### Reliability and responsible use

- **Proxy requirement** — Residential proxies are recommended. The default input uses the Apify RESIDENTIAL group.
- **Conditional fields** — Full description is collected only when job details are enabled. Salary fields are empty when Remote OK does not publish a range.
- **Public listings** — The Actor collects publicly visible Remote OK job data.
- **Responsible use** — Only use the data in ways that comply with Remote OK terms and applicable law.

### Frequently asked questions

#### Can I scrape Remote OK jobs by keyword and location?

Yes. Use `searchQueries` such as `python` and optionally add `locations` such as `US` or `Worldwide`. You can also paste a filtered Remote OK URL into `startUrls`.

#### Can I schedule Remote OK Scraper to run automatically?

Yes. Use the **Scheduler** tab in Apify Console. Daily suits sourcing; weekly suits salary snapshots.

#### What counts as one result?

Each job saved to the dataset is one `job` event ($1.00 per 1,000). If job details are enabled, each successful detail fetch also counts as a `job-details` event ($1.00 per 1,000).

#### Why are some fields empty?

`salaryMin` and `salaryMax` are empty when Remote OK does not show a range. Description is collected only when **Scrape job details** is enabled.

#### How do I avoid duplicate records?

The Actor does not deduplicate across runs. Use `id` as the stable key. `maxItems` caps a single run.

#### Do I need a proxy?

Residential proxies are recommended and are the default.

### Related Scraptivo automations

- [LinkedIn Job Scraper](https://apify.com/scraptivo/linkedin-job-scraper) — LinkedIn job listings.
- [Naukri Job Scraper](https://apify.com/scraptivo/naukri-scraper) — jobs from Naukri.com.
- [Glassdoor Jobs Scraper](https://apify.com/scraptivo/glassdoor-jobs-scraper) — Glassdoor job listings.
- [ZipRecruiter Scraper](https://apify.com/scraptivo/ziprecruiter-scraper) — ZipRecruiter job listings.

### Support and custom workflows

Need a different field, source, or delivery workflow? Contact Scraptivo at scraptivo@gmail.com. Include the Actor name, sample URL, required fields, and expected volume so we can assess the request.

# Actor input Schema

## `startUrls` (type: `array`):

Remote OK listing or job URLs from your browser (e.g. "https://remoteok.com/?order\_by=date", "https://remoteok.com/remote-dev-jobs", "https://remoteok.com/remote-jobs-in-singapore", or a single job page). Recommended when you already have a filtered URL. When provided, tags/location/benefits/search filters below are ignored for those URLs.

## `searchQueries` (type: `array`):

Free-text searches on Remote OK (e.g. "python", "staff engineer", "nurse"). Each query is scraped separately. Ignored when Start URLs are provided. Primary input for AI agents when you do not have a URL.

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

Job tags/categories to filter by (e.g. "dev", "medical", "backend", "seo"). Multiple tags are combined (AND). Ignored when Start URLs are provided.

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

Countries or regions where the job can be done (e.g. "Worldwide", "US", "NL", "SG", "region\_EU"). Each location is scraped as a separate search because Remote OK allows one location filter at a time. Ignored when Start URLs are provided.

## `benefits` (type: `array`):

Required job benefits (e.g. "401k", "async", "unlimited\_vacation", "4\_day\_workweek"). Multiple benefits are combined. Ignored when Start URLs are provided.

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

Minimum annual salary in USD (e.g. 30000, 80000, 150000). Matches the Remote OK salary filter (steps of $10,000, up to $250,000). Use 0 for no minimum. Ignored when Start URLs are provided.

## `sortBy` (type: `string`):

How to sort the job board (e.g. "date" for latest jobs, "salary" for highest paid). Applied to filter searches and to Start URLs that do not already include order\_by.

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

Maximum number of jobs to scrape (0 = unlimited)

## `scrapeJobDetails` (type: `boolean`):

When enabled, fetches each job's full page and merges richer fields (description, apply URL, benefits). You are charged per job (job) plus an additional event per successful details fetch (job-details).

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

Proxy settings for anti-bot protection. Apify Residential is recommended.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://remoteok.com/?order_by=date"
    }
  ],
  "searchQueries": [
    "python"
  ],
  "tags": [],
  "locations": [],
  "benefits": [],
  "minSalary": 0,
  "sortBy": "date",
  "maxItems": 10,
  "scrapeJobDetails": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

JSON array of scraped job listings at {{links.apiDefaultDatasetUrl}}/items

## `runStats` (type: `string`):

Record count and timestamps for this run

## `run` (type: `string`):

Apify Console link to inspect this run

# 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 = {
    "startUrls": [
        {
            "url": "https://remoteok.com/?order_by=date"
        }
    ],
    "searchQueries": [
        "python"
    ],
    "maxItems": 10,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scraptivo/remoteok-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 = {
    "startUrls": [{ "url": "https://remoteok.com/?order_by=date" }],
    "searchQueries": ["python"],
    "maxItems": 10,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("scraptivo/remoteok-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 '{
  "startUrls": [
    {
      "url": "https://remoteok.com/?order_by=date"
    }
  ],
  "searchQueries": [
    "python"
  ],
  "maxItems": 10,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call scraptivo/remoteok-scraper --silent --output-dataset

```

## MCP server setup

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