# Himalayas Remote Jobs Scraper (`nanoscrape/himalayas-jobs-scraper`) Actor

Scrape remote job listings from Himalayas: title, company, pay, seniority, contract type, allowed countries and time zones, categories, full description and dates. Filter by country, seniority, contract type, category, pay and date. Pay-per-result.

- **URL**: https://apify.com/nanoscrape/himalayas-jobs-scraper.md
- **Developed by:** [NanoScrape](https://apify.com/nanoscrape) (community)
- **Categories:** Jobs, Lead generation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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

Get the public remote job listings of Himalayas (himalayas.app) as one clean dataset. Browse the newest jobs or search by keyword, then narrow the result by country, seniority, contract type, category, pay and posting date. One row per job, with the full description, pay range, allowed countries and time zones.

### What you can do with it

- Build a daily feed of new remote jobs per field, for example Python, design or customer support, with the posting date on every row.
- Find remote jobs you may take from a given country, including jobs that are open worldwide.
- Compare pay ranges, seniority levels and contract types across remote roles.
- Find which companies hire remotely, with a link to each company page.
- Feed job boards, lead lists, market reports or alerts with structured data instead of web pages.

### What you get

One row per job. Fields a job does not carry are `null`, lists are always `[]` when empty.

| Field | What it holds |
|---|---|
| `id`, `guid` | Row id (`himalayas-<job id>`) and Himalayas' own identifier of the job (the job page URL) |
| `title`, `excerpt` | Job title and the short summary |
| `company`, `company_slug`, `company_logo_url`, `company_url` | Hiring company, its identifier, logo link and company page on Himalayas |
| `employment_type`, `seniority` | Contract type as posted (for example Full Time, Contractor) and the list of seniority levels the job is open to |
| `salary_min`, `salary_max`, `salary_currency`, `salary_period` | Pay range as posted. About a quarter of the jobs show pay. `salary_period` (annual, monthly, hourly) is `null` when there is no pay |
| `location_restrictions` | Countries the worker must live in. `[]` means the job is open worldwide |
| `timezone_restrictions` | Accepted time zones as UTC offsets in hours (for example `-5`, `5.5`) |
| `categories`, `parent_categories` | Category tags and the broader fields |
| `description`, `description_text` | Full job description as HTML and as plain text |
| `posted_at`, `expires_at` | Publication and expiry time (ISO 8601, UTC) |
| `apply_url`, `job_url` | Application link (tracking parameters removed) and the job page on Himalayas |
| `remote`, `source_query`, `match_source`, `scraped_at` | Always `true`, the keyword that found the job (empty for the newest-jobs feed), where it came from (`search` or `feed`, see below) and the collection time |

Every job appears once per run, even when several keywords or pages find it.

### Input

| Field | Type | Description |
|---|---|---|
| `searchQueries` | string list | Keywords such as a job title or skill. Each keyword returns the top 20 search hits plus matches among the newest jobs (see How keyword results work). Empty means the newest jobs first |
| `countries` | string list | Optional. ISO codes (`US`, `DE`) or names (`Germany`, `United Kingdom`). Keeps jobs a person living in one of these countries may take |
| `includeWorldwide` | boolean | With a country filter, also keep jobs without a country restriction. Default `true` |
| `seniority` | string list | Optional. `Entry-level`, `Mid-level`, `Senior`, `Manager`, `Director`, `Executive`. A job passes when it is open to at least one of them |
| `employmentType` | string list | Optional. Contract types as shown on the rows, for example `Full Time`, `Contractor` |
| `categories` | string list | Optional. A category or broader field, for example `Developer` or `Python-Developer`. The whole name must match |
| `minSalary` | integer | Only jobs whose pay range reaches this yearly amount. Hourly pay counts as 2,080 hours, monthly pay as 12 months. No currency conversion, jobs without pay are dropped. `0` means no limit |
| `postedWithinDays` | integer | Only jobs posted in the last N calendar days (UTC, today included). `0` means no limit |
| `maxResults` | integer | Total number of jobs over everything. Default `100`, `0` means no limit |
| `feedScanPages` | integer | With keywords: pages of 20 newest jobs to scan for keyword matches. Default `50` (the 1,000 newest jobs), maximum `2000`, `0` means search hits only |
| `maxResultsPerQuery` | integer | Jobs per keyword (or for the newest-jobs feed). Default `100`, `0` means no limit |

Lists also accept a comma or line separated text. Case, spaces and dashes do not matter for seniority, contract type and category (`full-time` matches `Full Time`). The country, seniority, contract type, category, pay and date filters are applied to the jobs found, before anything is charged.

#### Example: new senior Python jobs for Germany

```json
{
  "searchQueries": ["python"],
  "countries": ["DE"],
  "seniority": ["Senior"],
  "maxResults": 50
}
```

#### Example: everything posted in the last two days

```json
{
  "postedWithinDays": 2,
  "maxResults": 0
}
```

#### Example: well paid contractor jobs open to the US

```json
{
  "searchQueries": ["designer"],
  "countries": ["US"],
  "includeWorldwide": false,
  "employmentType": ["Contractor"],
  "minSalary": 80000
}
```

#### How keyword results work

A keyword run gives you two kinds of rows:

1. The top 20 search hits of Himalayas for the keyword, in relevance order (`match_source` is `search`).
2. Matches among the newest jobs. The actor reads the newest jobs page by page (`feedScanPages` pages of 20) and keeps those whose title, summary, categories or company contain your keyword (`match_source` is `feed`). Short words of up to 3 letters (such as `go` or `ai`) must match a whole word, longer words match inside words, case and accents do not matter, and a keyword of several words needs every word.

The newest jobs are read once per run for all your keywords, and a job goes to the first keyword (in your order) it matches. A job found by both ways is returned once. To widen a keyword run, raise `feedScanPages` (up to 2,000 pages = 40,000 jobs); to get search hits only, set it to `0`. With `postedWithinDays` the scan ends at the date window. The status message of the run tells how many newest jobs were scanned.

### Output

```json
{
  "id": "himalayas-8699633569",
  "guid": "https://himalayas.app/companies/acme/jobs/senior-python-engineer-8699633569",
  "title": "Senior Python Engineer",
  "company": "Acme",
  "company_url": "https://himalayas.app/companies/acme",
  "employment_type": "Full Time",
  "seniority": ["Senior"],
  "salary_min": 120000,
  "salary_max": 150000,
  "salary_currency": "USD",
  "salary_period": "annual",
  "location_restrictions": ["United States", "Canada"],
  "timezone_restrictions": [-8, -7, -6, -5],
  "categories": ["Python-Developer", "Backend-Engineer"],
  "parent_categories": ["Developer"],
  "posted_at": "2026-11-04T09:00:00Z",
  "expires_at": "2026-12-04T09:00:00Z",
  "apply_url": "https://himalayas.app/companies/acme/jobs/senior-python-engineer-8699633569",
  "job_url": "https://himalayas.app/companies/acme/jobs/senior-python-engineer-8699633569",
  "remote": true,
  "source_query": "python",
  "match_source": "search",
  "scraped_at": "2026-11-04T09:30:00Z"
}
```

The example is shortened and the values are illustrative. Real rows hold all fields of the table above.

### Pricing

Pay per result, two events:

- `apify-actor-start`: $0.001 once per run.
- `job-result`: $0.0009 per job in the dataset ($0.90 per 1,000 jobs).

Filtered-out and duplicate jobs are never charged. Set a maximum total charge on the run to stop at a budget; the run then ends cleanly with the message "Stopped at the max charge limit. N jobs delivered." The pricing box on the actor page always shows the current rates.

### Use with AI Agents (MCP)

Connect this actor to any MCP-compatible AI client, such as Claude Desktop, Claude.ai, Cursor, VS Code, LangChain, LlamaIndex, or custom agents.

**Example prompts once connected:**

> "Use `himalayas-jobs-scraper` to find senior Python jobs open to Germany posted in the last 3 days and list title, company and pay."

> "Use `himalayas-jobs-scraper` to list the newest contractor jobs with a published hourly rate."

Configure the MCP server with the Himalayas Remote Jobs Scraper preconfigured at `mcp.apify.com?tools=nanoscrape/himalayas-jobs-scraper`:

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=nanoscrape/himalayas-jobs-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}
```

See the auto-generated API tab on the actor page for language-specific examples (cURL, JavaScript, Python, and more).

### Related actors

- Randstad Jobs Scraper (`nanoscrape/randstad-jobs-scraper`): staffing jobs of Randstad in Germany, Switzerland and the UK.

### FAQ

**What does one run cost?**
A start fee plus one result fee per job in the dataset. Use `maxResults` or a maximum total charge to cap it.

**What does an empty `location_restrictions` mean?**
The job is open worldwide. With a country filter these jobs are kept unless you set `includeWorldwide` to `false`.

**Why do many jobs have no pay?**
Most postings do not publish pay. The pay fields are `null` for them, and a `minSalary` filter drops them.

**Why is `apply_url` the same as `job_url`?**
Himalayas sends applicants through the job page. The actor removes tracking parameters such as `utm_source` from the link and keeps the rest as published.

**Can I get only new jobs?**
Yes, set `postedWithinDays`. The newest jobs are read newest first and the run stops at the first job older than your window, so it reads only as many pages as needed.

**What if a search finds nothing?**
The run ends successfully with the message "0 jobs." and the reason, for example no hits or no job inside your filters.

### Limits

- Keyword search hits are limited to the top 20 per keyword. Matches beyond them come from the scan of the newest jobs, so older jobs that are not in the top 20 are only found within the `feedScanPages` window.
- Search hits come in relevance order, not by date, so `postedWithinDays` filters them but cannot end the search; it does end the scan of the newest jobs.
- Without keywords, a filtered read of the newest jobs stops after 40 pages in a row without a matching job.
- Pages are read one after the other with a short pause, so very large runs take a while.
- Only public listing data is returned. Pay is shown as the company posted it.
- You are responsible for using the data lawfully, including the GDPR/DSGVO, national data-protection laws and unfair-competition rules for marketing and outreach.

### Support

Questions, feature requests or a field you miss: <contact@nanoscrape.com>.

Built by NanoScrape. Not affiliated with Himalayas.

# Changelog

This Actor's version history is a separate document: https://apify.com/nanoscrape/himalayas-jobs-scraper/changelog.md

# Actor input Schema

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

One or more keywords such as a job title or skill. Each keyword returns the top 20 search hits plus matching jobs among the newest feed jobs (see Feed Scan Pages). Multi-word keywords need every word. Leave empty to list the newest jobs first. Jobs found twice are returned once.

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

Optional. Only jobs a person living in one of these countries may take are returned. Use ISO codes (US, DE) or names (Germany). Leave empty for all countries.

## `includeWorldwide` (type: `boolean`):

When you filter by country, also keep jobs that have no country restriction (open worldwide). Has no effect without a country filter.

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

Optional. Keep jobs open to at least one of these levels: Entry-level, Mid-level, Senior, Manager, Director, Executive. Case and dashes do not matter.

## `employmentType` (type: `array`):

Optional. Keep jobs with one of these contract types as Himalayas shows them, for example Full Time, Contractor. Case and dashes do not matter.

## `categories` (type: `array`):

Optional. Keep jobs tagged with one of these categories or broader fields, for example Developer or Python-Developer. The whole category name must match; case and dashes do not matter.

## `minSalary` (type: `integer`):

Only jobs whose pay range reaches at least this yearly amount (hourly pay counts as 2,080 hours a year, monthly pay as 12 months). The amount is compared in the currency the job uses, there is no conversion. Jobs without pay are dropped. 0 = no limit.

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

Only return jobs posted within the last N calendar days (UTC, today included). Older jobs are dropped before they are charged. 0 = no limit.

## `feedScanPages` (type: `integer`):

With keywords: how many pages of 20 newest jobs to scan for jobs whose title, summary, categories or company match a keyword, in addition to the top 20 search hits. 50 pages = the 1,000 newest jobs. Up to 2,000. 0 = search hits only. With Posted Within Days the scan stops at the date window. Ignored without keywords.

## `maxResults` (type: `integer`):

Maximum number of jobs in total over all searches. 0 = no limit.

## `maxResultsPerQuery` (type: `integer`):

Maximum number of jobs per keyword (or for the newest-jobs feed). 0 = no limit.

## Actor input object example

```json
{
  "searchQueries": [
    "python"
  ],
  "countries": [],
  "includeWorldwide": true,
  "seniority": [],
  "employmentType": [],
  "categories": [],
  "minSalary": 0,
  "postedWithinDays": 0,
  "feedScanPages": 50,
  "maxResults": 100,
  "maxResultsPerQuery": 100
}
```

# Actor output Schema

## `jobListings` (type: `string`):

Dataset containing the scraped Himalayas jobs.

# 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"
    ],
    "countries": [],
    "seniority": [],
    "employmentType": [],
    "categories": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("nanoscrape/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"],
    "countries": [],
    "seniority": [],
    "employmentType": [],
    "categories": [],
}

# Run the Actor and wait for it to finish
run = client.actor("nanoscrape/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"
  ],
  "countries": [],
  "seniority": [],
  "employmentType": [],
  "categories": []
}' |
apify call nanoscrape/himalayas-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nanoscrape/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/OtxGSRFlg4YRpzmP4/builds/gHz57kuuPMDDxQIuW/openapi.json
