# Himalayas Remote Jobs Scraper: Salaries & New-Job Alerts (`promur/himalayas-jobs-scraper`) Actor

Get remote jobs from Himalayas through its official free API: search by keyword, country, seniority, employment type, company and time zone, with salaries, categories and apply links. Monitor mode returns only new jobs, salary changes and closed jobs. No login.

- **URL**: https://apify.com/promur/himalayas-jobs-scraper.md
- **Developed by:** [PROMUR s.r.o.](https://apify.com/promur) (community)
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 jobs

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

## Himalayas Remote Jobs Scraper: Salaries & New-Job Alerts

Get **remote jobs from [Himalayas](https://himalayas.app)** - one of the largest remote job boards, 100,000+ open roles - by **keyword, country, seniority, employment type, company and time zone**, with **salaries**, categories, full descriptions and apply links, in one clean format ready for Excel, Google Sheets, Airtable, Slack or an AI agent. Or switch on the **change monitor** and get only what changed since your last run: **new jobs, salary changes, closed jobs** - a ready-made remote job alert.

The Actor uses Himalayas' **official, free, public Jobs API**. No scraping of web pages, no login, no browser. An API key is optional.

### Why this Actor

**Price, quality, reliability, responsibility - in balance:**

- 💵 **Low price** - $0.50 per 1,000 jobs; in monitor mode you pay only for new, changed or closed jobs.
- 🔍 **Clean, credited data** - salaries, seniority, locations, time zones and categories straight from Himalayas' official API, with the source credited on every row.
- 🔁 **Dependable runs** - paced to Himalayas' rate limits (your own free key raises them), a run report per search, a clean stop at your budget.
- 🤝 **Responsible collection** - the official free Jobs API only; Himalayas' robots.txt is respected, so a search returns its first 20 matches while the full feed has no limit.

**What you get:**

- 🔎 **Every API filter in one form** - search queries × countries, seniority, employment type, companies, time zone, worldwide only, sort (newest, highest salary ...).
- 💰 **Salaries as numbers** - minimum, maximum, currency and period (hourly, monthly, annual).
- 🌍 **Where you can work from** - the countries a job is open to (`isWorldwide` when anywhere) and the accepted UTC time zones.
- 🔔 **Job alerts** - one switch turns the scraper into a monitor. Each job gets a `changeType` (`new`, `changed`, `closed`). Unchanged jobs are not saved and **cost nothing**. Closed jobs are checked one by one with the API, so a job that only left your search is not reported as closed.
- 🗂️ **All remote jobs** - leave the search fields empty to walk the full feed; in monitor mode the walk stops as soon as it has caught up with the previous run.
- 🤝 **Plays by the API's rules** - paced to Himalayas' rate limit, apply links kept as the API gives them, a source credit on every row.

### Use cases

- **Remote job alerts** - a daily list of new senior Python jobs open to Germany, straight to Slack or email.
- **Job boards and newsletters** - curated remote roles for your own site or newsletter (see *Himalayas' terms* below).
- **Recruiting and sales intelligence** - which companies are hiring remotely, for which roles, at what salary.
- **Salary research** - pay ranges by role, seniority and country.
- **AI agents** - structured remote jobs via the Apify API or MCP server.

### How to use

1. Add one or more **Search queries** (e.g. `python developer`), and optionally **Countries**, **Seniority**, **Employment type**, **Companies** or **Time zone**.
2. Optional: set **Max jobs per search**, or turn on the **Change monitor** with a feed name.
3. Click **Start**. Download the results as JSON, CSV or Excel, or connect them to your tools. For alerts, schedule the Actor (Console → Schedules), e.g. every morning.

```json
{
    "searchQueries": ["python", "data engineer"],
    "countries": ["Germany"],
    "seniority": ["Senior"],
    "onlyChanges": true,
    "watchChanges": ["new"],
    "feedName": "senior-python-germany"
}
```

Each query × country pair is one search. Companies, seniority, employment type, time zone and the worldwide switches apply to every search. **Job links** (`https://himalayas.app/companies/<company>/jobs/<job>`) build a watchlist: in monitor mode you get a row when a job closes.

**API key (optional):** without a key, every caller shares Himalayas' public allowance and big runs may hit its rate limit (the run report then says `rate_limited`). With your own free key from himalayas.app you get 60 requests a minute and 10,000 a day (20 jobs per request). The key is stored encrypted and sent only to himalayas.app in a request header.

### Output

One row per job:

`jobId`, `title`, `companyName`, `companySlug`, `companyUrl`, `companyLogo`, `employmentType`, `seniority`, `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod`, `locations`, `isWorldwide`, `timezones`, `categories`, `parentCategories`, `excerpt`, `description`, `descriptionHtml`, `publishedAt`, `expiresAt`, `applyUrl`, `url`, `dataSource`, `changeType`, `changes`, `source`, `input`, `scrapedAt`.

```json
{
    "jobId": "micro1/software-engineer-open-3d-engine",
    "title": "Software Engineer (Open 3D Engine)",
    "companyName": "micro1",
    "employmentType": "Contractor",
    "seniority": ["Mid-level"],
    "salaryMin": 70,
    "salaryMax": 130,
    "salaryCurrency": "USD",
    "salaryPeriod": "hourly",
    "locations": [],
    "isWorldwide": true,
    "publishedAt": "2026-11-03T15:26:11.000Z",
    "applyUrl": "https://himalayas.app/companies/micro1/jobs/software-engineer-open-3d-engine?utm_source=api",
    "dataSource": "Data sourced from Himalayas (https://himalayas.app)"
}
```

| Field | Meaning |
| --- | --- |
| `locations` / `isWorldwide` | countries the job is open to; empty and `isWorldwide: true` = anywhere |
| `timezones` | accepted UTC offsets (empty = any) |
| `salaryPeriod` | `hourly`, `weekly`, `fortnightly`, `monthly` or `annual`; empty when the job shows no salary |
| `applyUrl` | the API's application link - use it for every "Apply" button (Himalayas' terms) |
| `changeType` | monitor mode: `new`, `changed` (salary) or `closed`, with a `changes` list (field, old, new) |
| `source` / `input` | `search`, `feed` or `job`, and the search or link it came from |

**Run report:** every run saves a `SUMMARY` record (Storage → Key-value store) with one entry per search: status, results on Himalayas, jobs read, jobs saved, new / changed / closed counts, and a plain-English message.

### Himalayas' terms (please read)

The data comes from the Himalayas Jobs API, and its terms (himalayas.app/terms#api) apply to how you use it:

- Use `applyUrl` (the API's application link) for every Apply action, not a direct employer link.
- Show a visible source credit with a link to himalayas.app (each row carries it in `dataSource`).
- You may show the jobs on your own job board, site or app; do **not** pass them on to other job boards, aggregators, Google Jobs or LinkedIn Jobs (including through feeds or JobPosting structured data).

### Pricing

**$0.50 per 1,000 jobs saved** - you pay only for results. Descriptions, salaries and categories are included.

- A search with 300 jobs: **$0.15**.
- A daily alert over 10 searches with ~50 new jobs a day: about **$0.03 a day**.

Set *Maximum cost per run* in the run options: the Actor saves jobs up to that amount and stops cleanly; in monitor mode the next run continues where it stopped. A job found by two searches in the same run is saved and charged once.

### FAQ

**How many jobs per search?** The first 20 matches of each search: Himalayas' robots.txt does not allow automated paging through search results, and we respect it. Narrow a search (country, seniority, employment type, company) to get the jobs you want, use the change monitor on a schedule to catch new jobs as they appear, or leave the search fields empty for the **full feed** (every remote job, no limit).

**How fresh is the data?** Himalayas refreshes the API data every 24 hours; jobs can close before their `expiresAt` date.

**Why `rate_limited` in the run report?** Without a key, all callers share one public allowance. Add your free Himalayas API key, or run fewer searches at once.

### Support

Need a filter or field? Open an issue on the **Issues** tab with your input and the run link - we usually fix it fast.

# Actor input Schema

## `searchQueries` (type: `array`):

Free-text searches, e.g. <code>python developer</code>, <code>product designer</code>, <code>customer support</code>. Each query runs with the filters below. Leave every search field empty to get <b>all remote jobs</b> on Himalayas.

## `countries` (type: `array`):

Jobs open to people in these countries (country name or ISO code, e.g. <code>Germany</code>, <code>US</code>, <code>Brazil</code>). Each country is a separate search.

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

Only jobs at these levels (any of them).

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

Only these employment types (any of them).

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

Only jobs at these companies: the Himalayas company slug (e.g. <code>gitlab</code>) or its link <code>https://himalayas.app/companies/gitlab</code>. Alone, this lists the open jobs at those companies (the first 20 per company).

## `timezone` (type: `string`):

Only jobs open to this time zone, e.g. <code>UTC+1</code>, <code>UTC-5</code>, <code>UTC+05:30</code>.

## `worldwideOnly` (type: `boolean`):

Only jobs open to people anywhere in the world.

## `excludeWorldwide` (type: `boolean`):

With Countries set: only jobs restricted to those countries, not jobs open worldwide.

## `sort` (type: `string`):

Order of search results. Default: most relevant (newest first in monitor mode).

## `jobUrls` (type: `array`):

Single jobs to fetch or watch, e.g. <code>https://himalayas.app/companies/\<company>/jobs/\<job></code>. In monitor mode you get a row when a job closes.

## `maxJobsPerInput` (type: `integer`):

Maximum jobs saved per search (query × country) or for the full feed. 0 = no limit. A search returns its first 20 matches (Himalayas' robots.txt does not allow paging through search results); the full feed has no such limit.

## `onlyChanges` (type: `boolean`):

Return only jobs that are new, changed salary or closed since your previous run with the same feed name. Unchanged jobs are skipped and cost nothing. The first run returns every job (your baseline). Ideal for daily job alerts.

## `watchChanges` (type: `array`):

Which changes are saved in monitor mode. For the full feed (no search fields) only new jobs are reported.

## `feedName` (type: `string`):

Keeps separate memories for separate monitors. Runs with the same feed name compare against each other. Stored in your own account (key-value store <code>himalayas-jobs-scraper-state</code>).

## `apiKey` (type: `string`):

Optional. Without a key all callers share Himalayas' public allowance. With your own free key (create it on himalayas.app) you get 60 requests a minute and 10,000 a day - about 1,200 jobs a minute. Stored encrypted; sent only to himalayas.app in a request header.

## Actor input object example

```json
{
  "searchQueries": [
    "python developer"
  ],
  "worldwideOnly": false,
  "excludeWorldwide": false,
  "maxJobsPerInput": 100,
  "onlyChanges": false,
  "watchChanges": [
    "new",
    "salary",
    "closed"
  ],
  "feedName": "default"
}
```

# Actor output Schema

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

One row per remote job: jobId, title, companyName, companyUrl, employmentType, seniority, salaryMin, salaryMax, salaryCurrency, salaryPeriod, locations, isWorldwide, timezones, categories, excerpt, description, publishedAt, expiresAt, applyUrl, url, dataSource, changeType, changes, source, input, scrapedAt.

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

One entry per search, feed or job link: status (ok, not_found, rate_limited, invalid, error, duplicate, skipped), results on Himalayas, jobs read, saved, new / changed / closed counts, and a plain-English message.

# 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 = {
    "searchQueries": [
        "python developer"
    ],
    "maxJobsPerInput": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("promur/himalayas-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 = {
    "searchQueries": ["python developer"],
    "maxJobsPerInput": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("promur/himalayas-jobs-scraper").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 '{
  "searchQueries": [
    "python developer"
  ],
  "maxJobsPerInput": 100
}' |
apify call promur/himalayas-jobs-scraper --silent --output-dataset

```

## MCP server setup

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

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/aIWeZgJXmemuCUUs2/builds/dwZ1p9EJrkPf2wsWd/openapi.json
