# RemoteOK Remote Jobs Scraper (`inlifeprojects/remoteok-jobs-scraper`) Actor

Scrape remote job listings from RemoteOK.com using their official public JSON API. Filter by skill tags, minimum salary, and keywords. Returns structured job data with salary, company info, tags, and direct apply links. No proxy or authentication needed.

- **URL**: https://apify.com/inlifeprojects/remoteok-jobs-scraper.md
- **Developed by:** [In life Projects Dev](https://apify.com/inlifeprojects) (community)
- **Categories:** Jobs, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## RemoteOK Remote Jobs Scraper

Fetches remote job listings from [RemoteOK's](https://remoteok.com) official public JSON API — no authentication, no proxy, no browser automation required. Each run returns up to ~100 of the most recent jobs per tag filter, normalized into a consistent `NormalizedJob` schema and pushed to an Apify Dataset. Supports optional webhook delivery for job board pipelines.

### ✨ Features

- Official RemoteOK JSON API — no browser, no proxy, no CAPTCHAs
- Filter by skill tags (javascript, python, react, devops, design etc.)
- Client-side keyword filter on title, company, tags
- Minimum salary filter (USD)
- Verified listings filter
- Non-tech role filter (optional)
- HTML stripped from descriptions — clean plain text output
- Webhook delivery in batches of 50 for job board pipelines
- Same NormalizedJob output schema as inlifeprojects/himalayas-jobs-scraper
- Results in under 5 seconds — extremely fast and cheap to run

### 🎯 Use Cases

- Job boards and aggregators
- Recruitment pipeline automation
- Salary research by tech stack
- Remote work trend monitoring
- AI agent job search workflows

### 📥 Input Parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `tags` | `string[]` | `[]` | Skill/category tags to filter by. Each tag is a separate API request. Leave empty for all recent jobs. |
| `keywordFilter` | `string` | `""` | Client-side keyword match against title, company, and tags. Case-insensitive. |
| `minSalary` | `integer` | `0` | Exclude jobs where `salary_max` is below this value (USD). Jobs without salary data always pass through. |
| `includeUnverified` | `boolean` | `true` | When `false`, only returns listings where `verified=true`. |
| `filterNonTech` | `boolean` | `false` | When `true`, removes clearly non-technical roles (receptionist, accountant, driver, nurse etc.). |
| `maxResults` | `integer` | `0` | Cap on total jobs returned across all tag requests. `0` means no limit. |
| `webhookUrl` | `string` | `""` | If set, POSTs all results to this URL in batches of 50 on completion. |
| `webhookSecret` | `string` | `""` | Sent as `X-Scraper-Secret` header with every webhook batch. |

### 📤 Output Format

Each item in the Apify Dataset conforms to the `NormalizedJob` schema:

```json
{
  "id": "senior-python-engineer-techcorp",
  "source": "remoteok",
  "source_url": "https://remoteok.com/remote-jobs/senior-python-engineer-techcorp",
  "apply_url": "https://techcorp.com/jobs/senior-python-engineer",
  "title": "Senior Python Engineer",
  "description": "We are looking for a Senior Python Engineer to join our backend team. You will design and build scalable APIs using Django and deploy them on AWS...",
  "type": "full-time",
  "work_mode": "remote",
  "location": "Worldwide",
  "experience_level": "",
  "salary_min": 130000,
  "salary_max": 160000,
  "currency": "USD",
  "salary_period": "year",
  "company_name": "TechCorp",
  "company_slug": "techcorp",
  "company_url": "https://remoteok.com",
  "company_logo_url": "https://remoteok.com/assets/companies/techcorp-logo.png",
  "tags": ["python", "django", "aws", "backend"],
  "markets": ["python", "django", "aws", "backend"],
  "posted_at": "2026-04-28T14:23:00.000Z",
  "expires_at": null,
  "scraped_at": "2026-04-29T09:00:00.000Z",
  "data_source": "RemoteOK",
  "data_source_url": "https://remoteok.com"
}
````

### 🚀 Example Inputs

#### Fetch all recent remote jobs (no filter)

```json
{}
```

Returns ~100 of the most recent jobs across all categories.

#### Filter by skill tags

```json
{
  "tags": ["javascript", "react", "typescript"],
  "minSalary": 80000,
  "filterNonTech": true
}
```

#### Job board pipeline with webhook

```json
{
  "tags": ["python", "javascript", "devops", "react"],
  "webhookUrl": "https://yoursite.com/api/internal/scraper/ingest",
  "webhookSecret": "your-secret-here"
}
```

#### Senior roles only with salary filter

```json
{
  "keywordFilter": "senior",
  "minSalary": 120000,
  "includeUnverified": false
}
```

### ⚡ Performance & Cost

- Single API request returns ~100 most recent jobs
- 4 tag filters = 4 API requests, ~400 jobs after deduplication
- Typical run: under 5 seconds
- Approximate Apify compute: 0.001–0.005 compute units per run
- Extremely cheap — well within Apify free tier

### 🏷️ Popular Tag Filters

```
javascript, typescript, python, react, vue, node, php, ruby, golang,
rust, java, kotlin, swift, flutter, devops, aws, docker, kubernetes,
design, ux, marketing, sales, finance, legal, hr, writing, customer-support
```

### 📋 Important Notes

- RemoteOK returns the ~100 most recent listings per tag request (not a full historical archive)
- Salary data is only available on ~30-40% of listings
- Salary currency is always USD on RemoteOK
- Employment type is always `"full-time"` — RemoteOK doesn't expose type in their API
- Attribution required: results include direct `source_url` links to RemoteOK per their terms of use

### 🔗 Also by inlifeprojects

- **[Himalayas Remote Jobs Scraper](https://apify.com/inlifeprojects/himalayas-jobs-scraper)** — search remote jobs from [Himalayas.app](https://himalayas.app) by keyword, seniority, employment type, and country. Supports full pagination up to 500 results per keyword with automatic deduplication.
- **[We Work Remotely Jobs Scraper](https://apify.com/inlifeprojects/weworkremotely-jobs-scraper)** — scrape remote job listings from [WeWorkRemotely.com](https://weworkremotely.com) — the world's largest remote work community — via their official public RSS feeds. 11 category feeds covering programming, devops, design, product, marketing, and more. No proxy or auth needed.

All three Actors share the same `NormalizedJob` output schema — run them together and combine the results with zero extra normalization work for maximum remote job coverage.

### 🙏 Attribution

Data sourced from [RemoteOK](https://remoteok.com) — the #1 remote-only job board on the web. Per RemoteOK terms: results link directly back to the original job listing on RemoteOK with no redirects.

### ⚠️ Limitations

- \~100 most recent jobs per tag (not full archive)
- Salary data sparse (~30-40% of listings)
- No pagination — RemoteOK API is a flat feed
- Rate limiting applies — built-in retry on 429

### 📝 Changelog

#### 0.1.0

- Initial release

# Actor input Schema

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

Filter jobs by skill or category tags. Each tag runs a separate API request. Results are deduplicated. E.g. \['javascript', 'python', 'react', 'devops', 'design']. Leave empty to fetch all recent jobs.

## `keywordFilter` (type: `string`):

Additional client-side keyword filter applied after fetching. Matches against job title, company name, and tags. Case-insensitive. E.g. 'senior', 'typescript', 'startup'.

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

Filter out jobs where salary\_max is below this value. Only applies to jobs that have salary data. Jobs without salary data are always included.

## `includeUnverified` (type: `boolean`):

When false, only returns listings where verified=true. When true, returns all listings regardless of verification status.

## `filterNonTech` (type: `boolean`):

When true, removes clearly non-technical roles (receptionist, accountant, driver, nurse etc.) from results.

## `maxResults` (type: `integer`):

Maximum total jobs to return across all tag requests. RemoteOK returns ~100 jobs per tag. Set to 0 for no limit.

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

If provided, POSTs all results to this URL in batches of 50 on completion.

## `webhookSecret` (type: `string`):

Sent as X-Scraper-Secret header with webhook delivery.

## Actor input object example

```json
{
  "tags": [],
  "keywordFilter": "",
  "minSalary": 0,
  "includeUnverified": true,
  "filterNonTech": false,
  "maxResults": 0,
  "webhookUrl": ""
}
```

# Actor output Schema

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

Scraped remote job listings. Each item contains title, company, salary, location, apply URL, tags, and metadata fields such as posted\_at and scraped\_at.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("inlifeprojects/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 = {}

# Run the Actor and wait for it to finish
run = client.actor("inlifeprojects/remoteok-jobs-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call inlifeprojects/remoteok-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=inlifeprojects/remoteok-jobs-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "RemoteOK Remote Jobs Scraper",
        "description": "Scrape remote job listings from RemoteOK.com using their official public JSON API. Filter by skill tags, minimum salary, and keywords. Returns structured job data with salary, company info, tags, and direct apply links. No proxy or authentication needed.",
        "version": "0.1",
        "x-build-id": "qEXfHotDp1V5jaxV3"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/inlifeprojects~remoteok-jobs-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-inlifeprojects-remoteok-jobs-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/inlifeprojects~remoteok-jobs-scraper/runs": {
            "post": {
                "operationId": "runs-sync-inlifeprojects-remoteok-jobs-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/inlifeprojects~remoteok-jobs-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-inlifeprojects-remoteok-jobs-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "tags": {
                        "title": "Skill tags (filter)",
                        "type": "array",
                        "description": "Filter jobs by skill or category tags. Each tag runs a separate API request. Results are deduplicated. E.g. ['javascript', 'python', 'react', 'devops', 'design']. Leave empty to fetch all recent jobs.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "keywordFilter": {
                        "title": "Keyword filter (optional)",
                        "type": "string",
                        "description": "Additional client-side keyword filter applied after fetching. Matches against job title, company name, and tags. Case-insensitive. E.g. 'senior', 'typescript', 'startup'.",
                        "default": ""
                    },
                    "minSalary": {
                        "title": "Minimum salary (USD)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Filter out jobs where salary_max is below this value. Only applies to jobs that have salary data. Jobs without salary data are always included.",
                        "default": 0
                    },
                    "includeUnverified": {
                        "title": "Include unverified listings",
                        "type": "boolean",
                        "description": "When false, only returns listings where verified=true. When true, returns all listings regardless of verification status.",
                        "default": true
                    },
                    "filterNonTech": {
                        "title": "Filter out non-tech roles",
                        "type": "boolean",
                        "description": "When true, removes clearly non-technical roles (receptionist, accountant, driver, nurse etc.) from results.",
                        "default": false
                    },
                    "maxResults": {
                        "title": "Max results",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Maximum total jobs to return across all tag requests. RemoteOK returns ~100 jobs per tag. Set to 0 for no limit.",
                        "default": 0
                    },
                    "webhookUrl": {
                        "title": "Webhook URL (optional)",
                        "type": "string",
                        "description": "If provided, POSTs all results to this URL in batches of 50 on completion.",
                        "default": ""
                    },
                    "webhookSecret": {
                        "title": "Webhook secret (optional)",
                        "type": "string",
                        "description": "Sent as X-Scraper-Secret header with webhook delivery."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
