Remote Jobs Aggregator - RemoteOK, WWR & Himalayas, No login avatar

Remote Jobs Aggregator - RemoteOK, WWR & Himalayas, No login

Pricing

Pay per event

Go to Apify Store
Remote Jobs Aggregator - RemoteOK, WWR & Himalayas, No login

Remote Jobs Aggregator - RemoteOK, WWR & Himalayas, No login

Remote job listings from Remote OK, We Work Remotely and Himalayas in one deduplicated dataset. Filter by keyword, category, region and date, get salary only when the board publishes it, and fetch only new jobs on scheduled runs. No login or API key for the boards.

Pricing

Pay per event

Rating

0.0

(0)

Developer

Cliqto Media

Cliqto Media

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

5 days ago

Last modified

Categories

Share

Remote Jobs Aggregator collects remote job listings from Remote OK, We Work Remotely and Himalayas and returns them as one dataset. The same job posted on two boards becomes one row. You can filter by keyword, category, location, date and salary, and on scheduled runs you can get only the jobs you have not seen before. You do not need a login or an API key for any of the boards.

Use it to build a remote job feed, a job alert or a salary dataset. The smallest run is one keyword: python, last 7 days, 50 jobs takes about 20 seconds and costs about $0.09.

Remote Jobs Aggregator: search Remote OK, We Work Remotely and Himalayas with one input and get one clean list of remote jobs — duplicates merged across boards, salary only when the board publishes it, only new jobs on scheduled runs

Table of contents

What it does

For each run the Actor:

  1. Reads the public job feeds of the boards you choose: the Remote OK public API, the We Work Remotely RSS feeds and the Himalayas public API. When you add keywords, Himalayas is searched with them; the other two boards are read in full and filtered.
  2. Keeps jobs that match your filters: keywords, exclude keywords, categories, allowed locations, posting date and "salary only".
  3. Merges the same job found on several boards into one row (same company and title, or the same link). The other boards are listed in alsoFoundOn.
  4. Writes the newest jobs first, up to Max jobs (maxItems).
  5. With Only new jobs (onlyNew), remembers which jobs it returned and skips them next time.

Each row has the job link on the board, the company, location, salary, tags, posting date and an optional description. The salary fields are filled only when the board publishes a salary. The Actor never estimates a salary.

Good fit

  • A daily or hourly remote job alert for one stack or role, without duplicates from three boards.
  • A dataset of remote jobs with published salary ranges for research or a newsletter.
  • A job board or Slack/Telegram feed that needs clean, structured rows with links back to the source board.

Not a fit / limits

  • Only these three boards. It does not read LinkedIn, Indeed, company career sites or boards that need a login.
  • It does not apply to jobs and does not collect data about candidates.
  • One run returns at most about 1,000 unique jobs, because that is what the three public feeds offer (see Limits).
  • Board data can be incomplete: some jobs have no salary, no location or no company website. Those fields are null.

Quick start

  1. Open the Input tab.
  2. The form already has Keywords (keywords) = python, Posted within (days) (postedWithinDays) = 7 and Max jobs (maxItems) = 50. Change the keyword if you like.
  3. Keep the other settings at their defaults: all three boards, description as plain text.
  4. Click Start.
  5. Open the Output tab. The Jobs view shows title, company, location, salary and the board.

Expected result: up to 50 Python remote jobs from the last 7 days from all three boards, newest first, in about 20 seconds. In our test runs 14–30% of rows had a published salary.

Input

All fields are optional. An empty input returns up to 100 jobs from the last 30 days from all three boards.

Input fields

FieldPlain nameTypeDefault / prefillAllowed valuesEffect
keywordsKeywordsarray of stringsdefault empty; prefill ["python"]up to 20, each up to 60 charactersKeep jobs that contain any of these words in title, tags, company or description. Whole words: python also matches pythonista, developer matches developers, but java does not match javascript. Also used as the Himalayas search query.
postedWithinDaysPosted within (days)integerdefault 30; prefill 71–90Keep jobs posted in the last N days. Jobs without a posting date are dropped.
maxItemsMax jobsintegerdefault 100; prefill 501–2000Upper limit of rows written and charged, after filters and duplicate merging.
sourcesJob boardsarrayall threeremoteok, weworkremotely, himalayasWhich boards to read.
excludeKeywordsExclude keywordsarray of stringsemptyup to 20Drop jobs whose title, tags or company contain any of these words, e.g. senior. The description is not checked.
searchInDescriptionMatch keywords in description toobooleantruetrue / falseOff: keywords match only title, tags and company (fewer, stricter results).
categoriesCategoriesarrayallprogramming, design, devops, product, sales-marketing, customer-support, management-finance, data, otherKeep only these categories. The category comes from the board or, if the board has none, from the job title.
locationsAllowedAllowed locationsarray of stringsanyup to 20, e.g. USA, UK, Europe, LATAM, APAC, GermanyKeep jobs open to these countries or regions. Worldwide jobs always pass. Jobs with an unknown location are dropped.
salaryOnlyOnly jobs with a salarybooleanfalsetrue / falseKeep only jobs where the board publishes a salary. We Work Remotely never publishes one, so it is skipped.
includeDescriptionDescription formatstringtexttext, html, both, nonePlain text (up to 20,000 characters), HTML (up to 50,000), both or none.
onlyNewOnly new jobsbooleanfalsetrue / falseSkip jobs returned in earlier runs with the same stateKey.
stateKeyState keystringdefault1–40 letters, digits or dashesSeparate memory for onlyNew, e.g. one key per saved search.
maxPagesPerSourceMax pages per boardinteger101–25Page limit for Himalayas (about 20 jobs per page). Higher finds older jobs but takes longer.

Interacting settings

WhenInput AInput BEffective behavior
Many keywordskeywordsmaxPagesPerSourceHimalayas gets 2 × maxPagesPerSource search pages in total, shared between the keywords (at least 1 page each). With 20 keywords, each keyword searches 1 page.
Keyword and exclude word both matchkeywordsexcludeKeywordsExclude wins. Exclude keywords check only title, tags and company.
Location filter and worldwide joblocationsAllowedjob isWorldwide = trueThe job passes any location filter.
Scheduled alertsonlyNewstateKeyEach stateKey has its own memory. Only rows that were written are remembered, so a job cut by maxItems can appear next time. Memory is kept for 120 days.

Input examples

Python jobs from the last week (the form prefill)

{
"keywords": ["python"],
"postedWithinDays": 7,
"maxItems": 50
}

Expected behavior: about 20 seconds, 50 rows from all three boards, newest first. Expected output: rows like the output example below. Cost: about $0.091 (one start plus 50 jobs on the Free plan).

Daily alert: new React jobs open to Europe, no senior roles

{
"keywords": ["react", "frontend"],
"excludeKeywords": ["senior", "lead"],
"locationsAllowed": ["Europe"],
"postedWithinDays": 3,
"maxItems": 200,
"onlyNew": true,
"stateKey": "react-europe"
}

Expected behavior: the first run returns all matching jobs; the next runs return only jobs not returned before for react-europe. Cost: you pay only for the new rows plus the start event.

Output

Each job is one row in the default Dataset. The run summary is in the Key-value store record RUN_SUMMARY.

Output example

One row from the prefill run (python, 7 days, 50 jobs). Shortened: the description fields are left out; all other fields are shown. Lemon.io posted the same job on Remote OK and We Work Remotely; it is one row with the second board in alsoFoundOn. Remote OK does not publish a location for this job, so the location fields are null.

{
"source": "remoteok",
"sourceJobId": "1137475",
"url": "https://remoteok.com/remote-jobs/remote-senior-react-full-stack-developer-lemon-io-1137475",
"applyUrl": "https://remoteok.com/remote-jobs/remote-senior-react-full-stack-developer-lemon-io-1137475",
"title": "Senior React Full stack Developer",
"company": "Lemon.io",
"companyUrl": null,
"location": null,
"regions": [],
"isWorldwide": null,
"remoteType": "remote",
"employmentType": null,
"category": "programming",
"salaryMin": 80000,
"salaryMax": 200000,
"salaryCurrency": "USD",
"salaryPeriod": "year",
"tags": ["python", "react", "node", "typescript", "full stack"],
"postedAt": "2026-10-09T13:09:18.000Z",
"alsoFoundOn": [
{ "source": "weworkremotely", "url": "https://weworkremotely.com/remote-jobs/lemon-io-senior-react-full-stack-developer-7" }
],
"attribution": "Job via Remote OK — https://remoteok.com",
"dedupKey": "lemon io|senior react full stack developer"
}

Output fields

FieldMeaningTypeCan be empty?Example
sourceBoard this row comes fromstringnohimalayas
sourceJobIdJob id on that boardstringnoa5-talent-finders/backend-engineer-latam-6204533411
urlJob page on the boardstringnohttps://himalayas.app/companies/…
applyUrlDirect apply linkstringyes, when the board has none
titleJob titlestringnoBackend Engineer LATAM
companyCompany namestringrarelyA5 Talent Finders
companyUrl, companyLogoCompany website or board page, logo URLstringyes
locationLocation as the board writes itstringyesMexico, Anywhere in the World
regionsCountries or regions the job is open toarrayempty when unknown or worldwide["Mexico"]
isWorldwideOpen worldwide?booleannull when the board does not sayfalse
remoteTyperemote, hybrid or onsitestringnoremote
employmentTypefull_time, part_time, contract, internship, temporary, otherstringyesfull_time
categoryNormalized categorystringnoprogramming
senioritySeniority as the board publishes itstringyesmid-level
salaryMin, salaryMaxSalary range as publishednumbernull when not published60000, 90000
salaryCurrencyISO currencystringnull when no salaryUSD
salaryPeriodyear, month, week, day or hourstringnull when no salaryyear
tagsTags or skills from the boardarraycan be empty["Python Developer", …]
postedAtPosting time, ISO 8601 UTCstringno2026-10-12T22:59:30.000Z
expiresAtExpiry timestringyes
descriptionText, descriptionHtmlDescription, depending on includeDescriptionstringyes
alsoFoundOnOther boards with the same jobarray of {source, url}empty when only one board
attributionSource credit you must showstringnoJob via Remote OK — https://remoteok.com
dedupKeyCross-board identity of the jobstringno`a5 talent finders
fetchedAtWhen this run fetched the jobstringno

Output views and run status

SituationWhere to lookWhat you seeWhat to do
Normal runOutput tab → Jobs, Salaries or Details viewOne row per jobExport or use the API
No job matches the filtersDataset is empty; RUN_SUMMARY.status = SUCCEEDEDcounts.filteredOut shows which filter removed the jobsWiden the date, remove a filter or a keyword
One board failedRows from the other boards; RUN_SUMMARY.status = PARTIALsources.<board>.status and errorRun again later; the rows you got are valid
All boards failedRun status Failed; RUN_SUMMARY.status = ERRORError code per boardRun again later or open an issue
Invalid inputRun status Failed with the field name in the messageNo rowsFix the field named in the message

RUN_SUMMARY also shows per-board counts, how many duplicates were merged, how many jobs onlyNew skipped and why the run stopped (stoppedBy).

Coming from another remote jobs Actor

The fields are not a drop-in copy of other job Actors. A simple mapping is usually enough: companyName → company, postedDate → postedAt, salary.min/max/currency/unit → salaryMin/salaryMax/salaryCurrency/salaryPeriod, companyWebsite → companyUrl, validThrough → expiresAt, applicantCountries → regions, jobLevel → seniority, employmentType list → one employmentType value, categories → category plus tags.

Pricing

Pricing unit

You pay per event:

EventWhenFreeBronzeSilverGold
Actor startonce per run$0.006$0.006$0.006$0.006
Job resultper row written to the Dataset$0.0017$0.0016$0.0015$0.0014

Platform usage (compute) is included. You pay for written rows only: jobs removed by filters, merged duplicates and jobs skipped by onlyNew are not charged. A run that finds no matching job costs only the start event, $0.006. A run with invalid input also costs only the start event.

If you set a maximum total charge for the run, the Actor stops writing rows before it would go over it and says so in RUN_SUMMARY.warnings.

Cost examples (Free plan)

ScenarioInputRowsCost
Prefillpython, 7 days, 50 jobs50about $0.091
Scheduled alert, quiet dayonlyNew, no new jobs0$0.006
Mediumno keywords, 30 days, 500 jobs500about $0.86
Everythingno keywords, 90 days, maxItems 2000, maxPagesPerSource 25about 930about $1.58

Use cases

Buyer jobInput pathOutput entityKey fieldsNext step
Job alert for one stackkeywords, onlyNew = true, a scheduleOnly new remote jobstitle, company, url, postedAtWebhook to Slack, email or a sheet
Salary researchcategories, salaryOnly = true, postedWithinDays = 90Jobs with published salarysalaryMin, salaryMax, salaryCurrency, salaryPeriodExport CSV or Excel
Remote job feed for a regionlocationsAllowed = ["Europe"]Jobs open to Europe or worldwidelocation, regions, isWorldwideAPI into your site
Market overviewno keywords, maxItems = 2000, postedWithinDays = 90All jobs the three feeds offercategory, tags, company, sourceDataset export

Scheduled runs and job alerts

  1. Save your input as a task, with onlyNew = true and a stateKey for this search, for example react-europe.
  2. Add a schedule to the task in Apify Console, for example every day.
  3. Each run returns only jobs not returned before for this stateKey. A quiet day costs only the start event ($0.006).
  4. To send the new rows somewhere, add a webhook or an integration (Slack, email, Google Sheets, Zapier, Make, n8n).

The memory is stored in your named key-value store remote-jobs-aggregator-state and keeps a job for 120 days. Use a new stateKey to start again.

API, export and integrations

  • API: start a run with POST https://api.apify.com/v2/acts/cliqtomedia~remote-jobs-aggregator/runs, your Apify API token and the input JSON. Read rows from the run's default Dataset.
  • Export: JSON, CSV, Excel, XML or RSS from the Output tab or the Dataset API.
  • Scheduling: see Scheduled runs and job alerts.
  • Webhooks / no-code: add a webhook on "Run succeeded" to send new rows to Zapier, Make, n8n, Slack or your own endpoint.

Use with AI agents (MCP)

  • MCP server URL with only this Actor: https://mcp.apify.com?tools=cliqtomedia/remote-jobs-aggregator.
  • Smallest useful input: {"keywords": ["python"], "postedWithinDays": 7, "maxItems": 50}.
  • Key output fields: title, company, url (job page), salaryMin/salaryMax/salaryCurrency (null when not published), postedAt, source.
  • A typical run takes about 20 seconds and costs about $0.09 for 50 jobs. maxItems is the main cost control; one run returns at most about 1,000 jobs.

Limits

  • About 1,000 unique jobs per run at most. The Remote OK feed has its ~100 newest jobs, the We Work Remotely feeds about 400, and Himalayas up to 25 pages of about 20 jobs. A run with no keywords, 90 days and maxPagesPerSource 25 returned 927 jobs in about one minute.
  • Himalayas depth per keyword. With a popular keyword and the default 10 pages, Himalayas returns about 180 of its newest matching jobs (for python that was the last ~16 hours). For more, raise maxPagesPerSource to 25 or run without keywords and filter afterwards.
  • Remote OK and We Work Remotely are read in full, then filtered, so keywords do not make them deeper.
  • Requests to each board are spaced (about one per second). All boards share one time limit: 120 seconds, or the run timeout minus 15 seconds if that is shorter. A run timeout under 30 seconds fails with TIMEOUT_TOO_SHORT.
  • Memory is fixed at 256 MB. A typical run takes 15–70 seconds.

Partial and failed runs

  • If one board fails, you still get rows from the other boards, and RUN_SUMMARY.status is PARTIAL. You pay only for the rows written.
  • If all boards fail, the run fails with status ERROR and no rows. You pay only the start event.
  • A run that is aborted keeps the rows already written; RUN_SUMMARY.status is CANCELLED.

Source terms you must follow

The jobs belong to the boards and the companies that posted them. When you show or republish rows:

  • Remote OK (API terms): link back to the job on Remote OK (url) and mention Remote OK as the source. Do not use the Remote OK logo. The attribution field has the text.
  • Himalayas (API terms): link back to the job on Himalayas (url) and mention Himalayas as the source. Do not submit Himalayas jobs to Jooble, Neuvoo, Google Jobs or LinkedIn Jobs.
  • We Work Remotely (RSS feed terms): link back to the job on We Work Remotely (url).

The Actor does not collect personal data about candidates. Job descriptions can include a recruiter's name or email; handle them under your local privacy rules.

Troubleshooting

The run succeeded but the Dataset is empty

Likely reason: the filters removed every job. Check: RUN_SUMMARY.counts.filteredOut shows how many jobs each filter removed (date, keywords, excluded, category, location, salary). Action: raise postedWithinDays, remove a filter or add another keyword.

Fewer Himalayas jobs than expected

Likely reason: the page limit. RUN_SUMMARY.sources.himalayas.notes says stopped at the page limit. Action: raise maxPagesPerSource (up to 25) or use fewer keywords.

Status is PARTIAL

Likely reason: one board did not answer or changed its feed. Check: RUN_SUMMARY.sources.<board>.error. Action: the rows you got are valid. Run again later. If it keeps failing, open an issue with the run ID.

onlyNew returns nothing

Likely reason: no new jobs since the last run with the same stateKey, or the new jobs did not match the filters. Action: this is normal for a quiet period. To start over, use a new stateKey.

FAQ

Do I need a login or API key for the boards?

No. The Actor uses only public feeds of the three boards. You need only your Apify account (and an Apify API token if you start runs through the API).

Why is the salary empty for many jobs?

Many companies do not publish a salary. The Actor copies the salary only when the board publishes it and never guesses one. Use salaryOnly to keep only jobs with a salary.

How fresh are the jobs?

Each run reads the boards at that moment. postedAt is the posting time from the board, fetchedAt is when the run read it. A closed job can still be in a feed until the board removes it.

How are duplicates found?

Two jobs are the same when the company and title match after normalization (case, punctuation, "Inc"/"Ltd" and similar removed), or when the link is the same. The row with the most details is kept; the other boards are listed in alsoFoundOn.

Can I add another board?

Not in this Actor. Boards that need a login or forbid reuse are not supported. For company career pages, see the Related Actors below.

Support

Open an issue in the Issues tab of this Actor. Include the run ID, your input (without private data) and the RUN_SUMMARY.status and message. Do not post tokens or personal data.