# Remote Jobs Feed API - Himalayas, Remotive, Arbeitnow (`thedeadpoet/remote-jobs-feed-api-himalayas-remotive-arbeitnow`) Actor

Search five public remote job feeds in one run - Himalayas, Remotive, Arbeitnow, We Work Remotely and Hacker News Who Is Hiring - deduplicated into a single remote-jobs schema with parsed salary ranges.

- **URL**: https://apify.com/thedeadpoet/remote-jobs-feed-api-himalayas-remotive-arbeitnow.md
- **Developed by:** [Pablo D](https://apify.com/thedeadpoet) (community)
- **Categories:** Jobs, Automation, Open source
- **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 listing returneds

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?

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 Jobs Feed API — Himalayas, Remotive, Arbeitnow, We Work Remotely & HN in one schema

**You want a live feed of remote jobs, and the good sources are five different APIs.** Himalayas paginates by cursor, Remotive returns everything in one shot, Arbeitnow pages 250 at a time, We Work Remotely is RSS per category, and Hacker News *Who is hiring?* is free text. This Actor queries all five in a single run and returns **one deduplicated remote-jobs dataset** with the same 22 fields on every row.

No API key. No proxy. No browser. No login.

```
Himalayas ──┐
Remotive  ──┤
Arbeitnow ──┼──►  dedup by company+title  ──►  one schema, alsoSeenOn trail
WWR       ──┤
HN hiring ──┘
```

### What problem this solves

Running five scrapers and merging their output by hand is the usual way to build a remote job feed. The merge is the annoying part: the same role is often carried by two boards under slightly different titles, and every feed names its fields differently. This Actor does the merge, and records **which other feeds carried the same job** in `alsoSeenOn`, so you keep the evidence instead of silently throwing a duplicate away.

### Use cases

- **Run a remote job board or newsletter** for a niche — Python, design, EU timezones — without maintaining five integrations that each break on their own schedule.
- **Remote job alerts at scale** — schedule a daily run with `postedWithinDays: 1` and you get only what is new since yesterday.
- **Labour-market research** — who is hiring remotely, for what, at what salary, over time.
- **Feed an LLM or RAG index** with fresh, structured, permissively-sourced job text.
- **Candidate sourcing in reverse** — see which companies are posting remote roles this week and in which categories.

### Sources

#### Himalayas

`himalayas.app/jobs/api` — public JSON with cursor pagination, **20 jobs per page**. The best of the five for structured fields: it is the main contributor of `salaryMin` / `salaryMax` / `currency`, `seniority` and `locationRestrictions`.

#### Remotive

`remotive.com/api/remote-jobs` — the public API Remotive publishes for third parties. Returns its whole current list in **one request**, and that list is small (17 jobs on 2026-09-10). Jobs keep their original `url`; please credit remotive.com when you republish.

#### Arbeitnow

`arbeitnow.com/api/job-board-api` — public job-board API and by far the deepest feed here (250 per page). Carries some on-site European roles as well as remote ones; those come back with `isRemote: false`.

#### We Work Remotely

The public per-category RSS feeds. Note that category slugs are not guessable — `remote-marketing-jobs` and `remote-sales-jobs` return **403**; the working slug is `remote-sales-and-marketing-jobs`.

#### Hacker News "Who is hiring?"

`hn.algolia.com/api/v1`, the official public HN search API, reading the current *Ask HN: Who is hiring?* thread. **Off by default**, because the thread is free text: titles are the comment's first line and company names are best-effort. Turn it on when you want the startup roles that never reach a job board.

### Input

```json
{
  "keywords": ["python", "data engineer"],
  "sources": ["remotive", "himalayas", "arbeitnow", "weworkremotely"],
  "locationKeywords": ["Europe", "Worldwide"],
  "postedWithinDays": 14,
  "excludeKeywords": ["senior manager"],
  "includeDescription": false,
  "deduplicate": true,
  "maxItems": 200,
  "maxPagesPerSource": 3,
  "requestDelaySeconds": 1
}
```

Leave `keywords` empty to pull everything the feeds currently publish.

### Output — one row per remote job

```json
{
  "source": "himalayas",
  "jobId": "https://himalayas.app/companies/netomi/jobs/software-development-engineer-in-test-i",
  "title": "Software Development Engineer In Test - I",
  "companyName": "Netomi",
  "companyLogo": "https://cdn-images.himalayas.app/...",
  "url": "https://himalayas.app/companies/netomi/jobs/...",
  "applyUrl": "https://himalayas.app/companies/netomi/jobs/...",
  "locationText": "India",
  "locationRestrictions": ["India"],
  "employmentType": "Full Time",
  "category": "Developer",
  "tags": ["SDET", "QA-Automation-Engineering"],
  "seniority": "Mid-level",
  "salaryText": null,
  "salaryMin": null,
  "salaryMax": null,
  "currency": null,
  "postedAt": "2026-09-09T14:12:17+00:00",
  "descriptionText": null,
  "isRemote": true,
  "alsoSeenOn": ["remotive"],
  "scrapedAt": "2026-09-10T10:31:02.884000+00:00"
}
```

`alsoSeenOn` lists the other feeds that carried the same job when `deduplicate` is on. `RUN_SUMMARY` in the key-value store records how many rows each feed returned and any feed that failed.

The dataset ships with three views: **overview** (including `alsoSeenOn`), **salary** (`salaryMin`, `salaryMax`, `currency`) and **full**.

### Honest limitations

- **Field coverage differs by feed.** Salary comes mostly from Himalayas; `employmentType` is missing from We Work Remotely; Hacker News has no structured fields at all. Fields a feed does not publish are `null`, never guessed.
- **Keyword filtering is client-side.** The feeds are fetched first and filtered after, so a narrow keyword with a low `maxPagesPerSource` can return very little. Raise `maxPagesPerSource` before concluding there are no matches — a measured run with keyword `python` returned 8 rows from 692 jobs fetched.
- **Deduplication is heuristic** — normalised company + title. Two genuinely different roles with the same title at the same company collapse into one row; turn `deduplicate` off if that matters.
- **Feed depth is finite and wildly uneven.** In a measured run: Arbeitnow 250, Hacker News 100, We Work Remotely 38, Himalayas 20, Remotive 18. So `maxPagesPerSource` buys very different amounts of data per feed.
- **This is a *current openings* tool, not a historical archive.** The feeds publish what is open now. If you want history, run it on a schedule and keep your own dataset.
- **Remote by nature.** These are remote job boards; Arbeitnow is the only one carrying meaningful on-site volume.
- **These feeds are free services.** They can rate-limit or change shape. The Actor retries with backoff and records per-feed errors in `RUN_SUMMARY` rather than failing the whole run.

### Pricing shape, and why

This Actor charges a small **start fee plus a per-job fee**. That is deliberate: its cost is driven by *fetching* 700–900 jobs, but a narrow keyword may push only 8 rows. Pure per-result pricing would make a precise, well-filtered search — the useful kind — the one that pays least.

### Attribution

`robots.txt` was checked for every host; none of these paths are disallowed. There is no login, captcha solving, proxy rotation or browser automation anywhere in this Actor. When you republish jobs, keep the original `url` and credit the source board.

### FAQ

**What is the best API for remote jobs?**
There is no single one. Himalayas has the best structured fields, Arbeitnow has the most volume, Remotive has the best-known brand and the smallest list. This Actor's answer is to read all of them and hand you one schema.

**How do I build a remote job board?**
Schedule this Actor daily with `postedWithinDays: 1`, `deduplicate: true` and your niche in `keywords`, then push the dataset into your site. `alsoSeenOn` tells you how widely a role is already listed, which is useful for ranking.

**Does this include work-from-home jobs that are not tech?**
Partly. Arbeitnow and We Work Remotely carry non-engineering categories (support, marketing, sales, design); Himalayas and Remotive skew technical. Use `keywords` and `excludeKeywords` to shape it.

**Is there a free remote jobs API?**
All five sources are free and public — that is why they were chosen. What you are paying for here is the querying, pagination, normalisation and deduplication across all five, not access to the data.

**Can I get salary data?**
Where the board publishes it. Use the **salary** dataset view: `salaryMin`, `salaryMax` and `currency` are parsed out of the raw `salaryText` where possible. Himalayas is the main contributor; expect `null` on many rows.

**Do I need a proxy?**
No. This Actor exposes no proxy input.

### Changelog

See `CHANGELOG.md`.

### Support

Found a bug, or need a field this Actor does not return yet? Open an issue on the Actor's **Issues** tab, or email **pablodevigoalertas@gmail.com**. Issues are read first.

# Actor input Schema

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

Case-insensitive. A job is kept if its title, company, tags or excerpt contains at least one of these. Leave empty to keep every job the feeds return.

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

Which public feeds to query.

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

Hard cap on the number of rows pushed. Keeps a broad search from running away with your budget.

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

0 = no date filter. Jobs with no publication date are always kept.

## `locationKeywords` (type: `array`):

Case-insensitive match against the location / hiring-region text, e.g. "Europe", "Worldwide", "USA", "Germany".

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

Case-insensitive. Jobs whose title contains any of these are dropped.

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

Adds the description text to every job. Makes the dataset much larger.

## `deduplicate` (type: `boolean`):

The same job often appears on more than one board. When on, near-duplicates (same company + normalised title) are collapsed into one row and the extra sources are listed in alsoSeenOn.

## `maxPagesPerSource` (type: `integer`):

Each page is one HTTP request (100-250 jobs). Raise it to reach deeper into the feeds.

## `requestDelaySeconds` (type: `number`):

Politeness delay between requests to the same feed.

## Actor input object example

```json
{
  "keywords": [
    "python",
    "data engineer"
  ],
  "sources": [
    "remotive",
    "himalayas",
    "arbeitnow",
    "weworkremotely"
  ],
  "maxItems": 200,
  "postedWithinDays": 0,
  "locationKeywords": [],
  "excludeKeywords": [],
  "includeDescription": false,
  "deduplicate": true,
  "maxPagesPerSource": 3,
  "requestDelaySeconds": 1
}
```

# Actor output Schema

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

One row per deduplicated remote job, with alsoSeenOn listing every feed carrying it.

# 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 = {
    "keywords": [
        "python",
        "data engineer"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("thedeadpoet/remote-jobs-feed-api-himalayas-remotive-arbeitnow").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 = { "keywords": [
        "python",
        "data engineer",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("thedeadpoet/remote-jobs-feed-api-himalayas-remotive-arbeitnow").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 '{
  "keywords": [
    "python",
    "data engineer"
  ]
}' |
apify call thedeadpoet/remote-jobs-feed-api-himalayas-remotive-arbeitnow --silent --output-dataset

```

## MCP server setup

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

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/QgxsZJZRIhCFoLJ5A/builds/LD7GCnMUvq8cEyTon/openapi.json
