# HH.ru Russia & CIS Job Listing Scraper (`jungle_synthesizer/hh-ru-russia-cis-job-listing-scraper`) Actor

Scrape live job vacancies from HH.ru across Russia, Ukraine, Kazakhstan, Belarus, Georgia, Azerbaijan, Kyrgyzstan, and Uzbekistan. Returns titles, salaries (gross/net), employer ratings, schedules, and full requirement/responsibility text for every listing.

- **URL**: https://apify.com/jungle\_synthesizer/hh-ru-russia-cis-job-listing-scraper.md
- **Developed by:** [BowTiedRaccoon](https://apify.com/jungle_synthesizer) (community)
- **Categories:** Jobs, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 record scrapeds

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

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## HH.ru Russia & CIS Job Listing Scraper

Scrape live job vacancies from [HH.ru](https://hh.ru), the dominant job board across Russia and the CIS. Returns titles, salaries (gross vs. net), employer ratings, work schedules, and full requirement/responsibility text for every listing across Russia, Ukraine, Kazakhstan, Belarus, Georgia, Azerbaijan, Kyrgyzstan, and Uzbekistan.

***

### HH.ru Scraper Features

- Covers all 9 areas on HH.ru's own facet — Russia plus 8 CIS countries — in a single run
- Extracts gross-vs-net salary distinction, not just a single number
- Returns employer trust flag, review rating, and review count per listing
- Filters by free-text keyword the same way HH.ru's own search box does
- Splits requirement and responsibility text out of the full job description where the posting is structured that way
- Includes work format (remote/hybrid/onsite), schedule, and employment type
- Handles pagination automatically across every selected area — you get the full result set, not one page

***

### Who Uses HH.ru Job Data?

- **Recruiters and staffing agencies** — benchmark salary ranges across regions before making an offer
- **Compensation analysts** — build pay bands from real gross/net postings instead of self-reported surveys
- **Market researchers** — track hiring demand by industry, region, or employment type across the CIS
- **Job board aggregators** — feed structured vacancy data into a meta-search product
- **Relocation and remote-work platforms** — filter for remote/hybrid postings across a specific country
- **Labor economists** — study wage dispersion and job growth patterns across Russia and neighboring states

***

### How HH.ru Scraper Works

1. Pick which areas to crawl (Russia, Ukraine, Kazakhstan, etc.) and an optional search keyword.
2. The scraper walks HH.ru's own search results for each selected area, page by page.
3. Each vacancy's detail page is visited for the fields the search results don't carry — schedule, employment type, publish date, and the requirement/responsibility split.
4. Records land in your dataset as they're collected, so you can start using data before the run finishes.

***

### Input

```json
{
    "areas": ["113"],
    "query": "python developer",
    "maxItems": 100
}
```

| Field       | Type    | Default | Description |
|-------------|---------|---------|-------------|
| `areas`     | array   | all     | Which HH.ru areas to crawl: Russia, Ukraine, Kazakhstan, Azerbaijan, Belarus, Georgia, Kyrgyzstan, Uzbekistan, or Other regions. Leave empty to crawl every area. |
| `query`     | string  | none    | Optional free-text keyword, matching HH.ru's own search box (e.g. `python developer`). Leave blank to crawl every vacancy in the selected areas. |
| `maxItems`  | integer | 10      | Maximum number of vacancies to return. |

#### Crawl all CIS countries with no keyword filter

```json
{
    "maxItems": 5000
}
```

***

### Resuming a large crawl

Every run emits a `resumeCursor` in its Output. If a large crawl stops before it finishes — because it hit `maxItems`, your spend cap (`maxTotalChargeUsd`), or was aborted — start a new run with **the same input** plus that `resumeCursor` to continue from where it left off. The crawl resumes from the queued work the previous run didn't reach.

- You are **not re-charged** for records the earlier run already delivered.
- Resume within your account's run-retention window — on the free tier, roughly your 10 most recent runs. Once the source run is pruned, its `resumeCursor` is no longer valid.
- `resumeCursor` is opaque — supply it unmodified.

***

### HH.ru Scraper Output Fields

```json
{
    "vacancy_id": "136008171",
    "title": "Водитель фронтального погрузчика",
    "employer_name": "РосРегион Развитие",
    "employer_id": "1238295",
    "employer_is_trusted": true,
    "employer_review_rating": 4,
    "employer_review_count": 37,
    "area_name": "Russia",
    "address": "Новосибирск",
    "metro_station": "Речной вокзал",
    "salary_min": 92000,
    "salary_max": 92000,
    "salary_currency": "RUB",
    "salary_is_gross": false,
    "experience_required": "Опыт 1-3 года",
    "vacancy_url": "https://hh.ru/vacancy/136008171",
    "work_schedule": "3/3",
    "work_format": "onsite",
    "employment_type": "Полная занятость",
    "snippet_requirement": "опыт работы не менее 1 года наличие прав категория Д ОБЯЗАТЕЛЬНО ...",
    "snippet_responsibility": "работа по погрузке щебня на территории карьера проведение ремонтных работ ...",
    "published_at": "2026-08-19T11:39:02.107+03:00",
    "has_response_letter": false,
    "scraped_at": "2026-08-20T06:14:02.507Z"
}
```

| Field                     | Type    | Description |
|---------------------------|---------|-------------|
| `vacancy_id`               | string  | HH.ru's own vacancy ID |
| `title`                     | string  | Job title |
| `employer_name`             | string  | Hiring company name |
| `employer_id`               | string  | HH.ru's own employer ID |
| `employer_is_trusted`       | boolean | Whether HH.ru has verified this employer |
| `employer_review_rating`    | number  | Average employer review rating, when the employer has reviews |
| `employer_review_count`     | number  | Number of employer reviews |
| `area_name`                 | string  | Country-level area this vacancy was crawled under |
| `address`                   | string  | City or district shown on the listing |
| `metro_station`             | string  | Nearest metro station, when applicable |
| `salary_min`                 | number  | Minimum stated salary |
| `salary_max`                 | number  | Maximum stated salary |
| `salary_currency`           | string  | Salary currency (e.g. `RUB`) |
| `salary_is_gross`           | boolean | `true` if the salary is stated before tax, `false` if net take-home |
| `experience_required`       | string  | Required experience level |
| `vacancy_url`                | string  | Direct link to the vacancy on HH.ru |
| `work_schedule`             | string  | Work schedule (e.g. `5/2`, `3/3`) |
| `work_format`                | string  | `remote`, `hybrid`, `onsite`, or the source's own wording when it doesn't map cleanly |
| `employment_type`           | string  | Employment type (full-time, part-time, etc.) |
| `snippet_requirement`       | string  | Requirements text extracted from the job description, when the posting uses a standard section header |
| `snippet_responsibility`    | string  | Responsibilities text extracted from the job description, when the posting uses a standard section header |
| `published_at`              | datetime| When the vacancy was published |
| `has_response_letter`       | boolean | Whether HH.ru requires a cover letter to apply |
| `scraped_at`                 | datetime| When this record was scraped |

***

### FAQ

#### How do I scrape HH.ru job listings?

Run this actor with no input beyond the defaults and it crawls every open vacancy across Russia and the CIS. Set `areas` to narrow it to specific countries, or add a `query` keyword to filter by role.

#### How much does HH.ru Scraper cost to run?

Pricing is pay-per-result at a standard per-record rate — check the Pricing tab on this actor's page for the current rate. There's no separate charge for the areas or keyword filters.

#### What data can I get from HH.ru?

Job title, employer name and trust status, salary (with the gross-vs-net distinction most competitors skip), location, work schedule and format, experience level, and the full requirement/responsibility text where the posting is structured that way.

#### Can I filter by country or region?

Yes. Set `areas` to one or more of Russia, Ukraine, Kazakhstan, Azerbaijan, Belarus, Georgia, Kyrgyzstan, or Uzbekistan. Leave it empty to crawl all of them in one run.

#### Do I need an account or API key for HH.ru?

No. HH.ru Scraper reads public vacancy pages — no HH.ru login or API key required.

***

### Need More Features?

Need custom fields, filters, or a different target site? [File an issue](https://console.apify.com/actors/issues) or get in touch.

### Why Use HH.ru Scraper?

- **Full CIS coverage** — one run reaches Russia and 8 neighboring countries on the same facet, not just the Russian market.
- **Salary detail competitors flatten away** — most HH.ru scrapers return one salary number; this one keeps the gross/net distinction and the min/max range separately, which is the difference between a usable comp dataset and a guess.
- **Employer signal included** — trust flag, review rating, and review count ride along with every listing, so you can screen postings without a second lookup.

# Actor input Schema

## `sp_intended_usage` (type: `string`):

What will this data feed? E.g. lead lists, KYB checks, price tracking.

## `sp_improvement_suggestions` (type: `string`):

Provide any feedback or suggestions for improvements.

## `sp_contact` (type: `string`):

We'll personally help with your use case. No spam.

## `resumeCursor` (type: `string`):

Leave empty for a fresh crawl. To CONTINUE a previous run where it stopped — without paying again for records you already received — paste the `resumeCursor` value from that run's Output (the run's OUTPUT key). Resume promptly: the previous run's data expires with your account's retention window (free tier: your ~10 most recent runs).

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

Maximum number of records to scrape

## `areas` (type: `array`):

Which countries on the hh.ru area tree to crawl. Leave empty to crawl all of Russia and the CIS: Ukraine, Kazakhstan, Azerbaijan, Belarus, Georgia, Kyrgyzstan, Uzbekistan, plus unclassified Other regions.

## `query` (type: `string`):

Optional free-text keyword to filter vacancies, matching hh.ru's own search box (e.g. python developer). Leave blank to crawl every vacancy in the selected areas.

## Actor input object example

```json
{
  "sp_intended_usage": "Describe your intended use...",
  "sp_improvement_suggestions": "Share your suggestions here...",
  "sp_contact": "Share your email here...",
  "maxItems": 10
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# 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 = {
    "sp_intended_usage": "Describe your intended use...",
    "sp_improvement_suggestions": "Share your suggestions here...",
    "sp_contact": "Share your email here...",
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("jungle_synthesizer/hh-ru-russia-cis-job-listing-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 = {
    "sp_intended_usage": "Describe your intended use...",
    "sp_improvement_suggestions": "Share your suggestions here...",
    "sp_contact": "Share your email here...",
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("jungle_synthesizer/hh-ru-russia-cis-job-listing-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 '{
  "sp_intended_usage": "Describe your intended use...",
  "sp_improvement_suggestions": "Share your suggestions here...",
  "sp_contact": "Share your email here...",
  "maxItems": 10
}' |
apify call jungle_synthesizer/hh-ru-russia-cis-job-listing-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jungle_synthesizer/hh-ru-russia-cis-job-listing-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/hI5QeMQZWAFDnOITQ/builds/OBNrQpARSAcHs9ZGD/openapi.json
