Remote Jobs API — RemoteOK, WWR, Himalayas & 4 More
Pricing
from $0.30 / 1,000 job returneds
Remote Jobs API — RemoteOK, WWR, Himalayas & 4 More
Seven remote job boards in one normalized feed: RemoteOK, Remotive, We Work Remotely, Himalayas, Jobicy, Working Nomads and Arbeitnow. Deduplicated across boards with an alsoOn list, full descriptions at no surcharge, filters applied before the charge, monitor mode for new jobs only. No API key.
Pricing
from $0.30 / 1,000 job returneds
Rating
0.0
(0)
Developer
Insight Solutions
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Seven public remote job boards in one schema, deduplicated across them: RemoteOK, Remotive, We Work Remotely, Himalayas, Jobicy, Working Nomads and Arbeitnow. Same columns, same run, same query.
Read straight from each board's own public feed. No API key, no login, no browser, no aggregator in the middle.
You are charged for the jobs you get, not the jobs we read. Every filter — keyword, location, salary, tag, timezone, date — is applied before the charge event. A run that reads 500 postings and returns 20 bills you for 20.
At a glance
Input — this is the Store prefill; paste it and run:
{"boards": ["remoteok", "remotive", "himalayas"],"keywords": ["developer", "engineer"],"maxJobs": 25,"remoteOnly": true,"monitor": false}
Output — one row per unique job posting; the fields you will use most are
title, company, applyUrl, board and postedAt (full list under Output
reference). Anything that could not be fetched comes back as a free diagnostic
row (ok: false, errorType, error) instead of a charge.
Price — $0.50 per 1,000 jobs on the FREE tier (+ $0.001 per run);
filtered-out jobs, cross-board duplicates, full descriptions, summary rows,
diagnostics and a monitor's baseline run are all free. Pay-per-event, no API
key, no browser, limited permissions — works over the Apify MCP server
(mcp.apify.com) and with agentic (x402) payments.
From code —
client.actor("insight.solutions/remote-jobs-api").call(run_input={…}) with
apify-client, or
POST https://api.apify.com/v2/acts/insight.solutions~remote-jobs-api/run-sync-get-dataset-itemsWhat you get
One row per unique posting. Same columns whichever board it came from:
{"rowType": "job","jobId": "himalayas:biocatch/sales-account-manager-iberia","board": "himalayas","boardJobId": "biocatch/sales-account-manager-iberia","url": "https://himalayas.app/companies/biocatch/jobs/sales-account-manager-iberia","applyUrl": "https://himalayas.app/companies/biocatch/jobs/sales-account-manager-iberia","company": "BioCatch","companyLogo": "https://cdn-images.himalayas.app/wb53l4a8sm9f3f8mqkjnyapvsoga","companyUrl": "https://himalayas.app/companies/biocatch","title": "Sales Account Manager Iberia","category": "Sales","categories": ["Sales"],"tags": ["Sales And Account Management", "B2B Sales", "Account Manager"],"employmentType": "FullTime","seniority": "manager","locationRaw": "Spain","countries": ["Spain"],"remoteRegions": null,"timezones": [0, 1],"isRemote": true,"workplaceType": "remote","salaryMin": null,"salaryMax": null,"postedAt": "2026-09-15T19:29:00.000Z","expiresAt": "2026-11-14T19:28:59.000Z","alsoOn": null,"alsoOnBoards": null,"source": "himalayas.app"}
…and the same row for a posting that turned up on three boards at once, with the other two folded into it:
{"rowType": "job","jobId": "himalayas:proxify/senior-data-engineer-azure","board": "himalayas","company": "Proxify AB","title": "Senior Data Engineer (Azure)","salaryMin": 70200,"salaryMax": 117000,"salaryCurrency": "USD","salaryPeriod": "YEAR","alsoOn": [{"board": "weworkremotely","url": "https://weworkremotely.com/remote-jobs/proxify-ab-senior-data-engineer-azure","applyUrl": "https://weworkremotely.com/remote-jobs/proxify-ab-senior-data-engineer-azure","boardJobId": "proxify-ab-senior-data-engineer-azure","postedAt": "2026-09-15T12:04:11.000Z"},{"board": "workingnomads","url": "https://www.workingnomads.com/job/go/1864102/","applyUrl": "https://www.workingnomads.com/job/go/1864102/","boardJobId": "1864102","postedAt": "2026-09-15T09:31:00-04:00"}],"alsoOnBoards": ["weworkremotely", "workingnomads"]}
That is one row and one charge, not three. The richest copy wins, its empty columns are filled in from the others, tags and countries are merged, and every place the job was found is on the row so you can still link to whichever board you like.
Quick start
Leave everything on its defaults and run it. You get the newest jobs from all seven boards, deduplicated, remote only.
Some things people actually ask:
| You want | Input |
|---|---|
| Remote Python jobs, anywhere | { "keywords": ["python"], "tags": ["python"] } |
| Senior engineering roles paying over $120k | { "keywords": ["engineer"], "seniority": ["senior", "staff", "principal"], "salaryMin": 120000 } |
| Jobs open to Europe, posted this week | { "locations": ["Europe"], "postedSince": "7d" } |
| Jobs an employer will hire across UTC−5 | { "timezones": [-5] } (Himalayas is the only board that publishes this) |
| Only jobs with a published salary | { "salaryOnly": true } |
| Full descriptions for an LLM pipeline | { "includeDescription": true, "descriptionFormat": "markdown" } |
| Everything one company is hiring for | { "companies": ["Proxify"] } |
| A daily alert of new jobs only | { "monitor": true } on a schedule |
| The deep board on its own | { "boards": ["himalayas"], "himalayasMaxPages": 50, "maxJobs": 0 } |
What each board actually gives you
Measured 2026-09-15. These are not marketing numbers — they are what one run returned, and the Actor will not pretend otherwise.
| Board | What one run returns | Freshness | Structured salary |
|---|---|---|---|
| RemoteOK | newest ~100 (the public API's cap; there is no paging) | newest first | bare numbers on ~12% of rows, labelled USD/year by board convention |
| Remotive | the whole public feed — 15 jobs today, job-count = total-job-count | delayed 24 hours by Remotive's own terms | free text only, 9 of 15 rows |
| We Work Remotely | 88 items — the newest ~10 per category, not the newest 88 on the board | newest first per category | none |
| Himalayas | 104,000+, paged 20 at a time | live | yes — min, max, currency and period on ~55% of rows |
| Jobicy | up to 200 per request | updated hourly | yes, ~50% of rows |
| Working Nomads | 50 | newest first | none |
| Arbeitnow | 250 per page, of which ~4% are flagged remote | updated hourly | none |
Himalayas is the board with depth. Remotive and We Work Remotely are small
today and are in the default list because they carry jobs the others do not, not
because they carry volume. Arbeitnow is a European aggregator: with remoteOnly
on it contributes about ten rows per page, and the 240 it does not contribute
are read and discarded for free — the board-summary row shows you exactly
that.
Input
| Field | Type | Default | What it does |
|---|---|---|---|
boards | multi-select | all seven | Which boards to read |
keywords | array | none | Title, tags and category must contain one of these |
excludeKeywords | array | none | Drop jobs containing one of these, description included |
keywordsMatchDescription | boolean | false | Extend keywords to the posting body |
categories | array | none | Match the board's own category names. Also picks which We Work Remotely category feed is fetched |
tags | array | none | Match the board's tags. The first entry is sent to RemoteOK as ?tag= |
locations | array | none | Free text over the location line, countries and remote regions. The first entry is sent to Jobicy as geo when it maps |
timezones | array of ints | none | UTC offsets the employer will hire across. Himalayas only |
employmentTypes | multi-select | none | FullTime, PartTime, Contract, Temporary, Internship, Volunteer, Other |
seniority | multi-select | none | intern … executive |
companies / excludeCompanies | array | none | Include or exclude employers by name |
salaryMin | integer | 0 | USD-per-year floor, compared to the top of the published range |
salaryOnly | boolean | false | Drop jobs with no published pay |
postedSince | string | none | ISO date or a relative window: 48h, 7d, 4w |
remoteOnly | boolean | true | Only bites on Arbeitnow; the other six are remote-only by construction |
maxJobs | integer | 100 | Per board, counted in matching rows. 0 = no cap |
maxJobsTotal | integer | 0 | Cap for the whole run, applied after the dedupe |
includeDescription | boolean | false | Add the full posting body. No surcharge |
descriptionFormat | select | text | text, markdown or sanitized html |
deduplicate | boolean | true | Collapse the same posting across boards into one charged row |
monitor | boolean | false | Return only postings never returned before |
stateStoreName | string | remote-jobs-api-state | The named key-value store the monitor remembers in |
firstRunBehavior | select | baseline-only | What the first monitor run does |
stateRetentionDays | integer | 45 | How long the monitor remembers a posting |
arbeitnowMaxPages | integer | 2 | Arbeitnow pages to read (2 MB each, ~10 remote rows each) |
himalayasMaxPages | integer | 10 | Himalayas pages to read (20 rows each) |
maxConcurrency | integer | 4 | Boards in flight |
maxRunSecs | integer | 240 | Wall-clock budget for the run |
requestTimeoutSecs | integer | 20 | Per-request timeout |
proxyConfiguration | object | Apify datacenter | Every board answered through it, and directly |
Output reference
Four row types, all in one dataset with the same columns:
rowType | What it is | Charged |
|---|---|---|
job | One unique posting that passed every filter | yes |
board-summary | One per board: what it read, what survived, what you paid for | no |
run-summary | The same for the whole run, plus duplicatesCollapsed | no |
diagnostic | One thing that could not be read, and why | no |
Identity and links: jobId, board, boardJobId, url, applyUrl,
alsoOn, alsoOnBoards.
Employer: company, companyLogo, companyUrl, companyDomain.
Role: title, category, categories, tags, employmentType,
seniority, excerpt, descriptionText, descriptionHtml.
Where: locationRaw, locations, countries, remoteRegions,
timezones, isRemote, workplaceType.
Money: salaryMin, salaryMax, salaryCurrency, salaryPeriod,
salaryRaw.
Time: postedAt, expiresAt, isNew, firstSeenAt.
The board summary is your receipt
Every run writes one free row per board:
{"rowType": "board-summary","board": "arbeitnow","pagesFetched": 2,"jobsFetched": 500,"jobsAfterFilters": 20,"jobsDeduped": 18,"jobsNew": 18,"jobsCharged": 18,"boardNotice": "This is a free public API for jobs, please do not abuse…"}
Five hundred postings read, twenty matched, eighteen billed. boardNotice
carries that board's own terms, in its own words, so the attribution obligation
travels with the data.
Salary
Salary is reported only where the board publishes it, and never inferred
from description text. Three of the seven publish structured pay; Remotive
publishes free text, which is parsed into numbers where it can be and kept
verbatim in salaryRaw either way. RemoteOK publishes bare numbers with no
currency and no period — it quotes annual USD on its own board, so that is what
is reported, and this sentence is the disclosure that it is a board convention
rather than something the feed stated. salaryMin compares against the top of a
range and converts an hourly or monthly rate for the comparison only; the
columns always hold exactly what the board published, in the currency it
published.
What you are never charged for
- Every job your filters excluded. The filters run before the charge, and an
excluded job does not even count toward
maxJobs. - Every duplicate collapsed across boards. One posting on three boards is one row and one charge.
- Every
board-summaryandrun-summaryrow. - Every diagnostic:
blocked,rate-limited,not-found,no-results,timeout,unavailable,parse-error,invalid-input,locked,budget-reached. - Every job already in the monitor's state.
- Descriptions. All seven feeds embed the full posting in their list response, so there is no second request to bill for and there is no description, salary or "detail" surcharge — not now and not later.
- A run that returns no job at all. It finishes FAILED, says why, and bills nothing, start fee included.
- A monitor's baseline run, and a monitor on a day with nothing new. See below.
Pricing
| Event | FREE | BRONZE | SILVER | GOLD |
|---|---|---|---|---|
| Run started | $0.001 | $0.001 | $0.001 | $0.001 |
| Job returned | $0.0005 | $0.0005 | $0.0004 | $0.0003 |
That is $0.50 per 1,000 jobs, descriptions included. There is one paid event and there will never be a second.
| Run | Rows | Cost |
|---|---|---|
The prefill — 3 boards, keywords: ["developer","engineer"], maxJobs: 25 | ~40 jobs | $0.001 + $0.020 = $0.021 |
All seven boards, no keyword filter, maxJobs: 0 | ~600 unique jobs | $0.001 + $0.300 = $0.301 |
| Daily monitor after the baseline, seven boards | ~40 new jobs | $0.001 + $0.020 = $0.021 |
Daily monitor, keywords: ["rust"], on a quiet day | 0 jobs | $0.00 — SUCCEEDED, free |
The run honours ACTOR_MAX_TOTAL_CHARGE_USD: when the budget runs out it stops
delivering rather than handing over rows it cannot bill for, finishes SUCCEEDED
and says so in the run status.
Running it every day: monitor mode
Set monitor: true and schedule it. Every run after the first returns only
postings this Actor has never returned before.
The first run is a baseline. It reads every board, records what is out
there, returns no job rows and charges for none of them, and finishes
SUCCEEDED with a status message saying so. That is deliberate and it is the
one documented exception to "a run with no job rows fails": a schedule's first
day is not a failure, and charging for a list of everything that already existed
would be charging for the wrong thing. Set firstRunBehavior: "emit-all" if you
would rather have the backfill and pay for it.
A later run on a day when nothing new was posted also finishes SUCCEEDED and costs nothing at all — not even the start fee. A scheduled job should not look broken because hiring was quiet.
isNew and firstSeenAt are on every row in both modes, so a non-monitor run
is still useful for your own diffing.
Where the state lives
An Actor's default key-value store is created fresh every run, so it cannot
carry yesterday's state. This Actor keeps state in a named store —
remote-jobs-api-state by default — which works within its limited
permissions: such an Actor may create storage, write to it, and re-open
storages it created in previous runs. Nothing else in your account is touched,
and limited permissions are a requirement for x402 agentic payments.
The one tradeoff: a limited-permissions Actor cannot read a store you
created by hand. If stateStoreName points at one you made in Console, the
Actor may not be able to open it — and it then logs a warning, treats the run as
a first run, and returns no job rows, so a permissions problem never becomes
a wave of jobs re-announced as new and re-charged. Let the Actor create its own
store and this never comes up.
One record holds every job the monitor has seen: a dedupe key, a date and a
short board list, about 70 bytes each. Entries older than stateRetentionDays
are pruned on every write and the record is capped at 50,000 jobs, oldest first.
Two overlapping scheduled runs would each diff against the same state and
double-report every job, so the second one takes one look at the run lock,
writes a free locked diagnostic and stops without fetching anything.
Proxy
The default is Apify's datacenter proxy, and it is the right default: every
one of the seven boards answered HTTP 200 through it, and HTTP 200 with no proxy
at all, in the capture probe. There is no residential leg anywhere in this
Actor. Switch proxyConfiguration to residential only if a board starts
refusing your runs; a board that refuses one exit IP is retried once from a new
one and then reported as a free blocked diagnostic rather than hammered.
Boards are read in parallel, never more than one request at a time against any one of them, with a pause between successive pages.
Use it from an AI agent, or from code
One JSON object in, one flat array out — the shape agent runtimes want. The Actor runs with limited permissions, uses pay-per-event pricing and never enters Standby, so it works over the Apify MCP server and with x402 agentic payments. The Integrations tab pushes results to Slack, a webhook, Zapier, Make, Google Sheets, Snowflake or BigQuery.
curl -X POST "https://api.apify.com/v2/acts/insight.solutions~remote-jobs-api/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"boards":["himalayas","remoteok"],"keywords":["rust"],"salaryMin":120000,"maxJobs":50}'
# pip install apify-clientfrom apify_client import ApifyClientclient = ApifyClient("<APIFY_TOKEN>")run = client.actor("insight.solutions/remote-jobs-api").call(run_input={"keywords": ["machine learning", "ml engineer"],"locations": ["Worldwide", "Europe"],"salaryOnly": True,"postedSince": "7d","includeDescription": True,"descriptionFormat": "markdown","maxJobs": 100,})for row in client.dataset(run["defaultDatasetId"]).iterate_items():if row.get("ok") and row["rowType"] == "job":print(row["title"], row["company"], row["board"],row["salaryMin"], row["salaryMax"], row["applyUrl"], sep=" | ")
Set monitor: true when you want an alert rather than a backfill: the run then
returns only postings it has not returned before.
FAQ
Do I need an API key for any of these boards? No. All seven publish a public feed, and this Actor reads nothing else. No login, no cookie that identifies anyone, no scraping behind a paywall.
Why is Remotive only fifteen jobs?
Because that is what Remotive's public API returns today — job-count and
total-job-count both say fifteen. It is not a page of a larger feed. Treat it
as a bonus board.
Why does Arbeitnow return so little?
Because it is a European job aggregator, not a remote board: roughly 4% of its
postings are flagged remote. Those 4% are real remote jobs the other six boards
do not have. The rest are read and dropped for free, and the board-summary row
shows you the ratio.
How does the cross-board dedupe decide two postings are the same job?
Company plus title, both normalised — legal suffixes dropped (OpenBase LLC and
OpenBase are one employer), bracketed qualifiers dropped ((m/w/d),
(Remote), (IR-471)), and a leading or trailing "remote" removed. It is
applied across boards only. Two postings on the same board that share a
company and a title are two requisitions — companies really do post "Senior
Software Engineer" twice for two teams — and collapsing those would lose a real
job.
Why does timezones only return Himalayas jobs?
Because Himalayas is the only one of the seven that publishes timezone
restrictions. A posting that says nothing about timezones is not "open to every
timezone", so it cannot satisfy a timezone filter.
Why is salaryMin null on so many rows?
Because most boards do not publish pay. Nothing here reads a number out of a
description and calls it a salary. Use salaryOnly: true if you only want rows
that have one.
Can I get the full job description?
Yes, includeDescription: true, in text, Markdown or sanitized HTML, at no
extra cost. Recruiter names, email addresses and personal profile links are
removed from it.
What happens if a board changes its format?
The feeds are public APIs, and their shape can change without notice. A board
that answers in a shape this Actor does not recognise produces a free
parse-error diagnostic row naming the URL, the other boards still deliver, and
the run only finishes successfully if it returned at least one real job.
Limitations
- The feeds are what the boards publish. Two of them are small today — Remotive 15 jobs, We Work Remotely 88 — and that is everything their public APIs have, not a page of something larger.
- RemoteOK has no paging. Its API serves the newest ~100 and stops. A
?tag=query returns a different hundred, which is the only way to go deeper. - We Work Remotely's all-jobs feed is the newest ~10 per category, so it is
not in date order across the feed. Set
categoriesto read a category feed instead. - Arbeitnow is a European ATS aggregator where roughly 4% of postings are
remote, and its pages are ~2 MB each. That is why
arbeitnowMaxPagesdefaults to 2. - Working Nomads returns a flat 50 with no paging parameter that we have found.
- Salary is only present where the board publishes it, and is never inferred from description text.
- Seniority is derived from the job title, except on Himalayas and Jobicy, which publish their own band.
- This Actor deliberately does no employer-email enrichment — contact lines
are stripped from
descriptionText— and does no scraping around any board's feed cap. Where a board publishes only its newest N, that is what you get, and the table above says which. - The upstream formats may change without notice. See the FAQ.
Attribution — please honour it
Every board here publishes its feed on terms. They are short, they are reasonable, and they are reproduced below in each board's own words. Every row carries the board it came from and that board's own job URL, so linking back is a copy of one field. You are responsible for honouring each board's terms in whatever you build.
- Remote OK — "Please link back (with follow, and without nofollow!) to the URL on Remote OK and mention Remote OK as a source, so we get traffic back from your site. If you do not we'll have to suspend API access." Also: do not use the Remote OK logo — it is a registered trademark — but the name is fine.
- Remotive — "Please link back to the URL found on Remotive AND mention Remotive as a source in order to Remotive to get traffic from your listing." Do not resubmit Remotive jobs to third-party boards (their notice names Jooble, Neuvoo, Google Jobs and LinkedIn Jobs). Using their listings to collect signups or email addresses breaches their terms. Their jobs are delayed 24 hours, and they ask for at most about four requests a day — this Actor makes exactly one per run.
- We Work Remotely — credit We Work Remotely and link to the job's own URL.
Their
robots.txtpermits the RSS paths this Actor reads. - Himalayas — link back to the original job URL and name Himalayas as the source.
- Jobicy — "Please ensure Jobicy is clearly credited with a direct link to the source, and all application buttons redirect to the original job URL provided in this feed." Their fair-use rule is at most one request per hour; this Actor makes one per run.
- Working Nomads — credit Working Nomads and link to the job URL. Their
robots.txtdisallows nothing. - Arbeitnow — "This is a free public API for jobs, please do not abuse. I would appreciate linking back to the site. By using the API, you agree to the terms of service present on Arbeitnow.com"
Each board's notice is also written into the dataset, on that board's
board-summary row, in the boardNotice column.
Our other Actors
Every Insight Solutions Actor is pay-per-result with no browser, no login and no API key, and every one of them returns free diagnostic rows instead of billing for failures. Prices are per 1,000 results.
Video, audio & social
- YouTube Transcript API — captions as timed segments, text, SRT or VTT, with language fallback and translation.
- YouTube Comments API — comments and replies with likes, pinned and hearted flags, newest or top sort.
- YouTube Channel API — a channel's videos, Shorts and live streams, plus YouTube search.
- Podcast Search, Episodes & Charts API — Apple Podcasts search, charts and full episode feeds.
- Bluesky Scraper — profiles, posts, followers and follows from the public AT Protocol API.
- Telegram Channel Scraper — posts, views and channel stats from public Telegram channels.
- Substack Scraper — posts with full free text, comments and publication profiles.
- Hacker News API — stories, comments, users, front page and a structured "Who is hiring?" parser from the official HN APIs.
News, documents & the web
- Google News Search, Topics & Real Article URLs — news search and topic feeds with the publisher's real URL decoded.
- Website to Markdown — Content Extractor for LLMs & RAG — any site as clean Markdown, text and heading-aware chunks.
- Internet Archive API — archive.org search, item metadata, files and reviews.
- Wayback Machine Toolkit — archived URL inventories, snapshots and text diffs between dates.
- Website Technology Detector — the tech stack behind any site, with the evidence for each detection.
- Domain Intelligence API — DNS, RDAP registration, TLS certificate and HTTP facts in one row per domain.
- SEO Page Audit — sitemap crawl with on-page checks, structured data and broken-link reports.
- Keyword Suggestions API — Google, YouTube, Bing, Amazon and eBay autocomplete with alphabet and question expansions.
- Website Contact Extractor — emails, phone numbers and social profiles from any list of websites.
- Web Search Results API — Bing and DuckDuckGo organic results with snippets, no key, no browser.
- Company Enrichment API — a domain in, a company profile out: firmographics, contacts, tech stack, DNS and hiring signal.
Business, finance & jobs
- Congress & Insider Trades API — STOCK Act periodic transaction reports and SEC Form 4 insider trades in one schema.
- Federal Contracts, Grants & Lobbying API — SAM.gov opportunities, USAspending awards, Grants.gov notices and Senate lobbying filings in one schema.
- SEC EDGAR API — filings, XBRL financials and full-text search by ticker or CIK.
- Clinical Trials & FDA API — ClinicalTrials.gov studies plus openFDA recalls, labels, approvals, 510(k)s and adverse-event reports.
- Product & Vehicle Recalls API — CPSC, NHTSA, FDA and USDA recalls, vehicle complaints and ratings, plus a VIN decoder.
- Y Combinator Companies, Batches & Founders — the YC directory with founders and social links, filterable by batch, industry and hiring status.
- Career Site Jobs API — jobs straight from Greenhouse, Lever, Ashby, Workable and 10+ other ATS career sites.
- New Job Postings Monitor — new, closed and changed postings on the career sites you watch.
- Shopify Products API — any Shopify store's catalogue, variants, prices and stock signals.
- Shopify Store Monitor — price drops, sales, restocks, sell-outs and new products on any Shopify store, one row per change.
Apps & games
- App Store & Google Play Reviews API — reviews from both stores with ratings, versions and developer replies.
- App Store Top Charts & App Search API — Apple top charts by country and genre, plus app search and details.
- App Store Keyword Rank Tracker — where any app ranks for any keyword on the App Store and Google Play, with rank changes and ASO suggestions.
- Steam Reviews API — Steam reviews with playtime, helpfulness and game details.
- Steam Game Data API — prices, tags, review scores, live player counts and top charts.