# Himalayas Remote Job Finder with Salary & Tech Stack (`vexaloom-labs/himalayas-remote-job-finder-with-salary-and-tech`) Actor

Search Himalayas remote job listings by keyword or company and get salary range, employment type, tech stack and job page link for each role.

- **URL**: https://apify.com/vexaloom-labs/himalayas-remote-job-finder-with-salary-and-tech.md
- **Developed by:** [vexaloom-labs](https://apify.com/vexaloom-labs) (community)
- **Categories:** Jobs, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.49 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 Job Finder with Salary & Tech Stack

Himalayas is a remote-first job board with roles from startups and established companies around the world. This actor turns its public listings into structured records: search by keyword, walk the newest jobs, pull a company's open roles, or resolve specific job URLs. When an employer publishes pay, each record carries the salary range, its pay period and an annualised comparison; every record also includes seniority, employment type, location and timezone restrictions, and optional job skills or company tech stack. No account, API key or proxy is required.

### What this actor does

- **Four modes:** `searchJobs`, `browseAll`, `byCompany`, `byJobUrls`
- **Remote-work filters:** country, worldwide-only, exclude worldwide, seniority, employment type, timezone and sort order
- **Salary done properly:** raw minimum/maximum plus `salaryPeriod` and annualised `salaryAnnualMin` / `salaryAnnualMax`
- **Optional enrichment:** per-job required skills and per-company tech stack
- **Clean records:** empty fields are omitted, so a record never contains a null or placeholder value
- **URL-safe identity:** every record has a stable `jobGuid` and a clean listing `jobUrl`; `applyUrl` is the link Himalayas publishes for applications

### Output per job

| Field | Description |
|---|---|
| `jobId` | Job slug from the listing URL |
| `jobGuid` | Canonical Himalayas listing URL; globally unique across companies |
| `jobUrl` | Clean link to the job on Himalayas |
| `applyUrl` | Application link exactly as Himalayas publishes it |
| `source` | Always `"Himalayas"` |
| `title` | Job title |
| `company` | Hiring company name |
| `companySlug` | Canonical company slug |
| `companyUrl` | Company profile on Himalayas |
| `companyLogo` | Company logo image URL, when published |
| `location` | First five accepted countries, or `"Worldwide"` |
| `locationRestrictions` | Full list of countries the job is open to; omitted when the job is open worldwide |
| `worldwide` | `true` when the job has no country restriction |
| `remotePolicy` | Always `"remote"` |
| `salaryMin` / `salaryMax` | Published pay range in the listing's own `salaryPeriod` |
| `salaryPeriod` | `annual`, `monthly`, `fortnightly`, `weekly` or `hourly` |
| `salaryAnnualMin` / `salaryAnnualMax` | Pay converted to a yearly figure for comparison |
| `salaryCurrency` | Currency code for the published pay range, when provided |
| `employmentType` | `full-time`, `part-time`, `contract`, `temporary`, `internship`, `volunteer` or `other` |
| `seniority` | Seniority levels the role targets |
| `techStack` | Himalayas job tags, including role and technology tags |
| `categories` | Broader parent categories, e.g. Developer, Data Science, Design |
| `skills` | Required skills, when **Include job skills** is on |
| `companyTechStack` | Company-level tools, when **Include company tech stack** is on and published |
| `companyTechStackCategories` | Company tech stack grouped by category, when available |
| `timezoneRestrictions` | UTC offsets the job accepts, e.g. `UTC-5`, `UTC+05:30`; omitted when the job accepts any timezone |
| `postedAt` | When Himalayas last updated the listing |
| `expiresAt` | Latest date the listing stays open |
| `excerpt` | Short plain-text summary |
| `description` | Full job description HTML |
| `recordType` | Always `"job"` |
| `scrapedAt` | When the record was scraped |

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string (required) | `searchJobs` | `searchJobs` keyword search; `browseAll` newest-updated feed; `byCompany` company openings; `byJobUrls` specific URLs |
| `searchQuery` | string | – | Keyword search, e.g. "data engineer" (mode=searchJobs) |
| `companySlug` | string | – | Company slug or URL; comma-separate several, e.g. "stripe,vercel" (mode=byCompany) |
| `jobUrls` | array | `[]` | Himalayas job URLs to resolve (mode=byJobUrls) |
| `country` | string | `""` (any) | Only jobs open to this country; worldwide jobs are included unless excluded |
| `worldwide` | boolean | `false` | Only jobs with no country restriction; overrides country |
| `excludeWorldwide` | boolean | `false` | With a country set, exclude jobs open worldwide |
| `seniority` | array | `[]` | Entry-level, Mid-level, Senior, Manager, Director, Executive |
| `employmentType` | string | `""` (any) | full-time, part-time, contract, temporary, internship, volunteer, other |
| `timezone` | string | – | Accepted UTC offset, e.g. `-5`, `UTC-5`, `UTC+05:30` |
| `categories` | array | `[]` | Match categories, parent categories or tech tags, e.g. "python", "developer" |
| `minSalary` | integer | – | Annualised salary floor |
| `maxSalary` | integer | – | Annualised salary ceiling |
| `salaryCurrency` | string | `""` (any) | Compare only jobs paid in this currency |
| `sortBy` | string | `recent` | relevant, recent, salaryAsc, salaryDesc, nameAToZ, nameZToA, jobs (browse mode is always newest-updated) |
| `includeSkills` | boolean | `false` | Fetch per-job required skills; one extra lookup per job (Himalayas' anonymous limit is 30/minute and 200/day) |
| `includeCompanyTechStack` | boolean | `false` | Fetch the employer's company-level tech stack once per company; shares the same lookup limit |
| `maxItems` | integer | `20` (prefill `3`) | Hard cap on emitted job records (1–5000) |

#### Example: senior Python roles with a salary floor

```json
{
  "mode": "searchJobs",
  "searchQuery": "python",
  "seniority": ["Senior"],
  "employmentType": "full-time",
  "minSalary": 120000,
  "salaryCurrency": "USD",
  "includeSkills": true,
  "maxItems": 50
}
```

#### Example: newest worldwide jobs

```json
{
  "mode": "browseAll",
  "worldwide": true,
  "maxItems": 200
}
```

#### Example: all open roles at two companies

```json
{
  "mode": "byCompany",
  "companySlug": "stripe,vercel",
  "maxItems": 100
}
```

#### Example: resolve specific job URLs

```json
{
  "mode": "byJobUrls",
  "jobUrls": [
    "https://himalayas.app/companies/sola-payments/jobs/senior-data-platform-engineer"
  ],
  "includeSkills": true
}
```

### Use cases

- **Remote job boards** — build a fresh feed with salary, seniority and location restrictions
- **Salary research** — compare annualised pay across roles, countries and currencies
- **Recruiting and sourcing** — monitor a target company's open roles and required skills
- **Tech hiring analytics** — track which technologies appear in remote job postings
- **Job alerts** — run on a schedule and filter by country, seniority, employment type or keyword
- **Data enrichment** — resolve a list of known Himalayas job URLs into structured records

### FAQ

**Do I need a Himalayas account, API key or proxy?**
No. The actor reads Himalayas' public job listings. There is no login, key or proxy setup.

**Why are salary fields missing on some jobs?**
Many employers do not publish pay on Himalayas. When a listing has no salary figures, all salary fields are omitted. The actor never fills them with estimates.

**What is the difference between `salaryMin` and `salaryAnnualMin`?**
`salaryMin` and `salaryMax` are the published numbers in `salaryPeriod` — which may be hourly, monthly or annual. `salaryAnnualMin` and `salaryAnnualMax` convert those numbers to a yearly figure so different listings can be compared. For example, 50 USD/hour becomes 104,000 USD/year.

**Does the salary filter convert between currencies?**
No. The filter compares annualised numbers in the listing's own currency. Set `salaryCurrency` to compare only jobs paid in one currency, for example USD. Always read `salaryCurrency` alongside the figures. Jobs without a published salary are excluded whenever a salary floor, ceiling or currency filter is set.

**Why did I get at most 5,000 results for a keyword?**
Himalayas caps keyword searches at 5,000 results. Use `browseAll` to walk the full newest-updated feed, or add country, seniority or employment filters to narrow the search. The run status tells you when the cap was reached.

**How do I collect every listing on Himalayas?**
Use `browseAll` with a high `maxItems`. The actor follows Himalayas' cursor and never repeats a job; the feed currently holds more than 130,000 live listings. `searchJobs` and `byCompany` send country, worldwide, seniority, employment type, timezone and sort filters to Himalayas. `browseAll` applies country, seniority, employment type, timezone, salary and category filters in the actor, so a narrow filter can scan many pages; `maxItems` counts matches, not scanned jobs.

**Why are `skills` missing when I turn on Include job skills?**
Not every listing exposes a skill list, and Himalayas' public lookup limit allows 30 job/company lookups per minute and 200 per day without an account. The actor stops enrichment when that limit is reached and keeps the base records. For a large run, split it into smaller runs, run enrichment on a shortlist, or leave enrichment off.

**Why is `companyTechStack` missing?**
Company tech stacks are optional on Himalayas and many employers do not publish one. When a company has no stack, the field is omitted.

**Why was one of my job URLs skipped?**
A URL is skipped when it is not a Himalayas `/companies/<slug>/jobs/<job>` link, when the job no longer exists, or when it has closed. Salary and category filters also apply in this mode, so a resolved job that does not match is skipped too; the status message reports how many URLs were closed or invalid.

**Is this actor affiliated with Himalayas?**
No. It is an independent actor that reads Himalayas' public job data and links back to the original listings. Himalayas is the source of the data.

# Actor input Schema

## `mode` (type: `string`):

What to scrape. `searchJobs` runs a keyword search with filters. `browseAll` walks the newest-updated feed. `byCompany` returns a company's open roles. `byJobUrls` checks specific job URLs.

## `searchQuery` (type: `string`):

Free-text keyword search (mode=searchJobs). Leave blank to page through the newest searchable listings. Himalayas caps keyword searches at 5,000 results.

## `companySlug` (type: `string`):

Canonical company slug or Himalayas company URL, e.g. `stripe` or `https://himalayas.app/companies/stripe`. Comma-separate several slugs, e.g. `stripe,vercel`.

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

Himalayas job page URLs, e.g. `https://himalayas.app/companies/stripe/jobs/senior-engineer`. Closed or invalid URLs are skipped.

## `country` (type: `string`):

Only jobs open to this country. Leave blank for any country. Worldwide jobs are included unless Exclude worldwide is on.

## `worldwide` (type: `boolean`):

Only jobs with no country restrictions. Overrides the country filter.

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

When a country is set, exclude jobs that are open worldwide. Requires country.

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

Keep jobs at any of these seniority levels. Leave empty for all levels.

## `employmentType` (type: `string`):

Keep jobs of this employment type. Leave blank for all types.

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

Keep jobs that accept this UTC offset, e.g. `-5`, `UTC-5` or `UTC+05:30`. Leave blank for any timezone.

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

Keep jobs whose categories, parent categories or tech tags contain any of these terms (case-insensitive), e.g. `python`, `react`, `developer`.

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

Annualised salary floor. Hourly, weekly and monthly pay is converted to a yearly figure before comparison. Use salaryCurrency to compare in a specific currency.

## `maxSalary` (type: `integer`):

Annualised salary ceiling. Jobs whose annualised range starts above this value are excluded.

## `salaryCurrency` (type: `string`):

Only compare and keep jobs paid in this currency. Leave blank to compare each listing in its own currency (no conversion is applied).

## `sortBy` (type: `string`):

Search result order. Browse mode always uses newest-updated order.

## `includeSkills` (type: `boolean`):

Fetch each job's required skills from Himalayas job details. Adds one lookup per job; the public anonymous limit is 30 lookups per minute and 200 per day, so large runs keep base records and stop enrichment at the limit.

## `includeCompanyTechStack` (type: `boolean`):

Fetch the employer's company-level tech stack once per company. Many companies do not publish one, so this field is often absent. Shares the same anonymous lookup limit.

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

Hard cap on the number of job records emitted (1–5000).

## Actor input object example

```json
{
  "mode": "searchJobs",
  "searchQuery": "software engineer",
  "jobUrls": [],
  "country": "",
  "worldwide": false,
  "excludeWorldwide": false,
  "seniority": [],
  "employmentType": "",
  "categories": [],
  "salaryCurrency": "",
  "sortBy": "recent",
  "includeSkills": false,
  "includeCompanyTechStack": false,
  "maxItems": 3
}
```

# Actor output Schema

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

Dataset containing all scraped Himalayas remote job records.

# 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 = {
    "mode": "searchJobs",
    "searchQuery": "software engineer",
    "jobUrls": [],
    "country": "",
    "worldwide": false,
    "excludeWorldwide": false,
    "seniority": [],
    "employmentType": "",
    "categories": [],
    "salaryCurrency": "",
    "sortBy": "recent",
    "includeSkills": false,
    "includeCompanyTechStack": false,
    "maxItems": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("vexaloom-labs/himalayas-remote-job-finder-with-salary-and-tech").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 = {
    "mode": "searchJobs",
    "searchQuery": "software engineer",
    "jobUrls": [],
    "country": "",
    "worldwide": False,
    "excludeWorldwide": False,
    "seniority": [],
    "employmentType": "",
    "categories": [],
    "salaryCurrency": "",
    "sortBy": "recent",
    "includeSkills": False,
    "includeCompanyTechStack": False,
    "maxItems": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("vexaloom-labs/himalayas-remote-job-finder-with-salary-and-tech").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 '{
  "mode": "searchJobs",
  "searchQuery": "software engineer",
  "jobUrls": [],
  "country": "",
  "worldwide": false,
  "excludeWorldwide": false,
  "seniority": [],
  "employmentType": "",
  "categories": [],
  "salaryCurrency": "",
  "sortBy": "recent",
  "includeSkills": false,
  "includeCompanyTechStack": false,
  "maxItems": 3
}' |
apify call vexaloom-labs/himalayas-remote-job-finder-with-salary-and-tech --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,vexaloom-labs/himalayas-remote-job-finder-with-salary-and-tech"
        }
    }
}
```

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/Hd9yFj2ejcfGhmuYa/builds/cNQtmjcIwQjWeE4SR/openapi.json
