# Remote Jobs API: Remote Jobs by Region from Company Sites (`cleanrowdata/remote-jobs-api`) Actor

Remote-only jobs straight from 17,000+ company career sites (Greenhouse, Lever, Workday, Ashby...), refreshed hourly. Filter by where you can work from (US, Canada, Europe, UK, LATAM, APAC, anywhere), function, seniority and minimum salary. Aggregators removed, duplicates merged.

- **URL**: https://apify.com/cleanrowdata/remote-jobs-api.md
- **Developed by:** [Clean Row Data](https://apify.com/cleanrowdata) (community)
- **Categories:** Jobs, Automation, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

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 jobs by region, straight from 17,000+ company career sites

**Get remote jobs you can actually take from where you live.** This Actor returns **remote-only jobs** from **17,000+ companies' own career sites** (Greenhouse, Lever, Ashby, Workday, Workable, SmartRecruiters, Recruitee, Personio, Rippling), refreshed **every hour** (Workday daily), and tells you **where each remote job is open to**: US, Canada, Latin America, UK, Europe, India, Asia-Pacific, Middle East, Africa or anywhere. Ask for *"remote engineering jobs open to people in Europe, posted this week, paying $150k+"* and get clean rows with the employer's apply link in **a few seconds**.

Remote job boards and LinkedIn are full of reposts, aggregators and "remote" jobs that turn out to be US-only or hybrid. Here every row is a **direct employer posting**, hybrid and on-site roles are removed, job aggregators are excluded, and the same role posted once per country is **merged into one row** with all its countries.

### Why people use it

- 🌍 **Remote eligibility parsed for you**: `remote_regions` and `remote_countries` from location text like "Remote - US", "Remote, EMEA", "Remotely in Germany", "Anywhere", "LATAM". Filter with **Remote from**.
- 🧹 **Clean remote list**: hybrid and on-site jobs dropped, aggregators (Jobgether and similar) excluded, multi-country duplicates merged. **70,000+ open remote jobs**, about **7,000+ new per week**.
- 🧭 **Function and seniority**: every job classified into 15 functions (Engineering, AI / ML, Data, Product, Design, Sales, Marketing, Customer success...) and 8 levels (Intern to Director/VP).
- 💰 **Minimum salary in USD**: hourly and monthly pay annualized, so "at least $120,000" works across postings.
- ⚡ **Fast and fresh**: windows of the last **hour, 24 hours, 7 days, 30 days** or all open remote jobs.
- 💸 **$2.50 per 1,000 jobs**, pay only for rows returned.

### Quick start

1. Click **Start**. The prefilled input returns the **50 newest remote jobs open to people in the US, posted in the last 7 days** (about $0.13).
2. Pick your **Remote from** regions, add **Job title contains** or **Job functions**, and optionally a **Minimum annual salary**.
3. Export to **CSV, Excel, JSON or Google Sheets**, or call it from the API, Make, Zapier, n8n or an AI agent.

### Use cases and ready-to-paste inputs

#### 1. Remote job boards and newsletters: a clean weekly feed

Fill your board with "Last 7 days", then schedule **hourly with "Last hour"** (or daily with "Last 24 hours") for new jobs only.

```json
{
  "timeRange": "7d",
  "eligibleFrom": ["europe"],
  "jobFunctions": ["engineering"],
  "limit": 100
}
```

#### 2. High-paying remote roles (US)

```json
{
  "timeRange": "7d",
  "eligibleFrom": ["us"],
  "jobFunctions": ["engineering", "data", "ai_ml"],
  "minSalaryUsd": 150000,
  "limit": 200
}
```

#### 3. Remote jobs open to Latin America

```json
{
  "timeRange": "7d",
  "eligibleFrom": ["latam"],
  "limit": 100
}
```

Jobs open "anywhere" / worldwide always match. Turn off **Include remote jobs with no region stated** to get only jobs that explicitly name your region.

#### 4. Canada only, explicitly

```json
{
  "timeRange": "7d",
  "eligibleFrom": ["canada"],
  "includeUnspecifiedRegion": false,
  "limit": 100
}
```

#### 5. Entry and mid-level remote customer support jobs

```json
{
  "timeRange": "7d",
  "titleSearch": ["customer support", "customer success"],
  "seniority": ["entry", "mid"],
  "eligibleFrom": ["us"],
  "limit": 100
}
```

#### 6. Labor-market research: the whole remote market

Set **Posted in the last** to "All open remote jobs" and **Max jobs** to 5,000 (split by function for more).

### Sample output

Real rows from the default input (remote, open to the US, last 7 days), October 2026:

| Title | Company | Remote from | Function | Seniority | Salary (annual) |
|---|---|---|---|---|---|
| Software Engineer, Agent Optimization & Evaluation | Reddit | us | engineering | mid | |
| Strategic Account Executive, Northeast | GitLab | us | sales | mid | |
| Staff Data Analyst | Cribl | us | data | staff_principal | |
| Director, Strategic Growth | Savvy | us | marketing | executive | $350,000 |
| Machine Learning Engineer, Answers Relevance | Reddit | us | ai_ml | mid | |
| Senior Director, Client Operations | Engine | us | operations | executive | |

One full row:

```json
{
  "id": "a15f4a9cca9d08de",
  "title": "Director, Strategic Growth",
  "company": "Savvy",
  "ats": "ashby",
  "board": "savvy",
  "job_function": "marketing",
  "seniority": "executive",
  "remote_regions": ["us"],
  "remote_countries": ["United States"],
  "location": "Remote - US",
  "locations": ["Remote - US"],
  "workplace_type": "remote",
  "employment_type": "FULL_TIME",
  "department": "Growth",
  "salary_min": 350000,
  "salary_max": 350000,
  "salary_currency": "USD",
  "salary_period": "YEAR",
  "salary_text": "$350K",
  "salary_annual_min": 350000,
  "salary_annual_max": 350000,
  "posted_at": "2026-10-19T00:03:23Z",
  "first_seen": "2026-10-19T00:29:16Z",
  "job_url": "https://jobs.ashbyhq.com/savvy/d82be631-2069-498f-b7ca-b61ec58752dd",
  "apply_url": "https://jobs.ashbyhq.com/savvy/d82be631-2069-498f-b7ca-b61ec58752dd/application"
}
```

**Example dataset** (a full default run, free to download): [CSV](https://api.apify.com/v2/datasets/lgEl532oK2v61WQ3w/items?format=csv) · [JSON](https://api.apify.com/v2/datasets/lgEl532oK2v61WQ3w/items?format=json) · [Excel](https://api.apify.com/v2/datasets/lgEl532oK2v61WQ3w/items?format=xlsx)

Each run also writes a **Run summary** (`RUN_SUMMARY`): jobs matched and returned, duplicate listings merged and **when the index was last refreshed**.

### How it compares

| | **Remote Jobs API (this Actor)** | Remote job board scrapers | LinkedIn / Indeed scrapers | [Job Postings API](https://apify.com/cleanrowdata/fresh-jobs-index) (our full index) |
|---|---|---|---|---|
| Source | Employers' own ATS boards | One board's listings | Job board listings, reposts | Employers' own ATS boards |
| Coverage | 70,000+ remote jobs, 17,000+ companies | One board | Search results | All 1.17M jobs, remote and on-site |
| Where can I work from? | ✅ parsed regions + countries | sometimes | ❌ | ❌ (text match only) |
| Hybrid / aggregators removed | ✅ | varies | ❌ | ❌ |
| Function, seniority, annualized salary filter | ✅ | ❌ | partial | ❌ |
| Speed | Seconds | Minutes | Minutes, proxies | Seconds |
| Price | $2.50 / 1,000 jobs | $1-$3 / 1,000 | varies | $2.50 / 1,000 jobs |

### Pricing (pay per event)

| Event | Price |
|---|---|
| Job returned (row in the dataset) | **$0.0025** (= **$2.50 per 1,000 jobs**) |
| Actor start | $0.00005 (Apify's standard start event) |

Examples: the default input (50 jobs) = **$0.13**. A daily feed of 200 new remote jobs = 6,000 jobs/month = **$15/month**. Set **Max jobs** and the run stops exactly there.

### Coverage and freshness

- Built on the same index as the [Job Postings API](https://apify.com/cleanrowdata/fresh-jobs-index): **1,177,389 open jobs** from **20,281 verified boards** on 9 ATS platforms, of which **70,000+ are remote** after removing hybrid jobs, aggregators and duplicates.
- Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Recruitee, Personio and Rippling are refreshed **every hour**; Workday **once a day**. The `RUN_SUMMARY` shows the exact last refresh.
- 1h, 24h and 7d answer in seconds. 30 days and "all" scan the full index (1-2 minutes).

### FAQ

**How do you decide where a remote job is open to?**
From the job's location text and country (for example "Remote - US", "Remote (Canada)", "EMEA", "Remotely in Germany", "Anywhere", US state names and codes, Canadian provinces). "Anywhere" / worldwide jobs match every region. Jobs that only say "Remote" have no region (`remote_regions: []`); keep or drop them with **Include remote jobs with no region stated**.

**What counts as remote?**
Jobs the ATS marks as remote or whose location says remote. Jobs marked hybrid or on-site are excluded unless a location explicitly says remote.

**Why are some jobs merged?**
Companies often post the same remote role once per country. We merge them into one row (same company and title) and list all regions, countries and locations.

**Do you have job descriptions?**
No. Use the [Careers Page Jobs Scraper](https://apify.com/cleanrowdata/careers-jobs-feed) for full descriptions of specific companies.

**Is it legal?**
The index only contains job postings that companies publish through their ATS's public job-board endpoints, the same data their careers pages show to everyone. No personal data.

### Limitations

- Region parsing is rule-based on what the company wrote; unusual phrasing may leave `remote_regions` empty.
- Salary filters only use salaries the ATS publishes as structured data (USD for **Minimum annual salary**).
- Up to 5,000 jobs per run.
- No job descriptions.

### Related Actors (same hourly jobs index)

- [Job Postings API: 1M+ Fresh Jobs](https://apify.com/cleanrowdata/fresh-jobs-index): search all jobs (remote and on-site) by title, location and time window.
- [Hiring Signals API: Companies Hiring Now](https://apify.com/cleanrowdata/hiring-signals-api): one row per hiring company, with new jobs by function and seniority. Sales and recruiting leads.
- [Careers Page Jobs Scraper](https://apify.com/cleanrowdata/careers-jobs-feed): live scrape of the companies you choose, with full descriptions and a new/closed jobs feed.

Questions or a missing feature? Open an issue on the Actor's **Issues** tab.

# Changelog

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

# Actor input Schema

## `eligibleFrom` (type: `array`):

Return remote jobs open to people in any of these regions, parsed from each job's location text ('Remote - US', 'Remote, EMEA', 'Anywhere', 'Remote - Canada'...). Worldwide/anywhere jobs always match. Empty = all remote jobs.

## `includeUnspecifiedRegion` (type: `boolean`):

Some jobs just say 'Remote'. Keep them (on) or only return jobs whose region explicitly matches (off).

## `timeRange` (type: `string`):

Only jobs posted (or first seen) in this window. 1h/24h/7d answer in seconds; 30d and all scan the full 1.17M-job index (1-2 minutes).

## `titleSearch` (type: `array`):

Only jobs whose title contains any of these. E.g. 'python', 'product designer', 'account executive'.

## `titleExclusionSearch` (type: `array`):

Skip jobs whose title contains any of these. E.g. 'senior', 'manager'.

## `jobFunctions` (type: `array`):

Only these kinds of roles (classified from title and department). Empty = all.

## `seniority` (type: `array`):

Only these levels (parsed from the title). Empty = all.

## `minSalaryUsd` (type: `integer`):

Only jobs that publish a USD salary whose annualized top of range is at least this (hourly/monthly pay is annualized). Leave empty to include jobs without salary.

## `hasSalary` (type: `boolean`):

Only jobs whose posting includes a pay range.

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

Only jobs mentioning any of these in title, department, team or company.

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

Skip jobs mentioning any of these.

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

Only these employment types (when the ATS states them).

## `companies` (type: `array`):

Only companies whose name or board contains any of these.

## `companyExclusion` (type: `array`):

Skip companies whose name or board contains any of these.

## `ats` (type: `array`):

Only companies on these applicant tracking systems. Leave empty for all 9.

## `excludeAggregators` (type: `boolean`):

Skip aggregators and recruiting marketplaces (e.g. Jobgether) that repost thousands of other companies' 'remote' jobs. Every row is then a direct employer posting.

## `limit` (type: `integer`):

Maximum jobs to return, newest first. You pay per job.

## Actor input object example

```json
{
  "eligibleFrom": [
    "us"
  ],
  "includeUnspecifiedRegion": true,
  "timeRange": "7d",
  "hasSalary": false,
  "excludeAggregators": true,
  "limit": 50
}
```

# Actor output Schema

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

Matching remote jobs, newest first.

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

Counts and index freshness.

# 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 = {
    "eligibleFrom": [
        "us"
    ],
    "timeRange": "7d",
    "limit": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("cleanrowdata/remote-jobs-api").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 = {
    "eligibleFrom": ["us"],
    "timeRange": "7d",
    "limit": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("cleanrowdata/remote-jobs-api").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 '{
  "eligibleFrom": [
    "us"
  ],
  "timeRange": "7d",
  "limit": 50
}' |
apify call cleanrowdata/remote-jobs-api --silent --output-dataset

```

## MCP server setup

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

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/E6M8JwsG1iD21YZmA/builds/eJQR5Eeum6VNY2y2R/openapi.json
