HeadHunter RU $1๐ฐ URL | Filters | Enriched Job Data
Pricing
from $1.00 / 1,000 results
HeadHunter RU $1๐ฐ URL | Filters | Enriched Job Data
From $1/1K. Scrape hh.ru job listings with 50+ fields including salary, experience, schedule, employment, and role. Search by filters or use URLs. Detail enrichment adds full descriptions, key skills, contact info, and employer logos.
Pricing
from $1.00 / 1,000 results
Rating
0.0
(0)
Developer
AbotAPI
Maintained by CommunityActor stats
0
Bookmarked
40
Total users
16
Monthly active users
11 days ago
Last modified
Categories
Share
hh.ru Jobs Scraper
Pull rich job listings from hh.ru (HeadHunter), Russia's largest job board, with 50+ fields per record. Filter by keywords, area, experience, schedule, employment, salary, and professional role; or paste search URLs directly. Detail-page enrichment adds full descriptions, key skills, contact info, and employer logos.
Why this scraper?
- 50+ fields per vacancy, 4x richer than typical hh.ru scrapers. Includes
keySkills, full HTML description, employer logos, GPS coordinates, metro stations, salary ranges (from/to + currency + gross/net), work formats, and contact info when public. - Three modes: pick keywords + area + filters, paste hh.ru search URLs as-is, or hand in a list of specific vacancy URLs / IDs and get the full detail card for each.
- Concurrent detail-page enrichment with per-record streaming push: results show up in the dataset as they finish, mid-run aborts preserve partial progress.
- Free-tier friendly: works on Apify default datacenter proxy, no residential plan needed.
- Full filter coverage: experience, employment, schedule, salary range, only-with-salary, professional role, industry, sort order.
- Forward-walking pagination that respects hh.ru's 40-page (2000-listing) hard cap per filter.
Data you get
Sample shape, values are illustrative placeholders, not from a live listing.
| Field | Example |
|---|---|
vacancyId | "100000001" |
url | "https://hh.ru/vacancy/100000001" |
name | "Sample Job Title" |
publicationDate | "2026-05-05T09:00:00.000+03:00" |
creationDate | "2026-05-01T09:00:00.000+03:00" |
lastChangeTime | "2026-05-04T09:00:00.000+03:00" |
validThroughTime | "2026-06-04T09:00:00.000+03:00" |
salaryFrom | 200000 |
salaryTo | 300000 |
salaryCurrency | "RUR" |
salaryGross | false |
salaryMode | "MONTH" |
salaryFrequency | "TWICE_PER_MONTH" |
area.id | 1 |
area.name | "ะะพัะบะฒะฐ" |
area.path | ".113.1." |
address.city | "ะะพัะบะฒะฐ" |
address.street | "Sample Street" |
address.lat | 55.7558 |
address.lng | 37.6173 |
address.metroStations | [{ "name": "Sample Station", "lineColor": "#000000" }] |
address.district | "Sample District" |
company.id | 1000000 |
company.name | "Sample Company" |
company.visibleName | "Sample Company" |
company.isAccreditedIT | true |
company.isTrusted | true |
company.siteUrl | "https://www.example.com/" |
company.logoUrl | "https://hh.ru/employer-logo-original/0000000.png" |
company.logos | [{ "type": "ORIGINAL", "url": "..." }, ...] |
company.badges | [{ "type": "hrbrand", "description": "Sample badge" }] |
workExperience | "between1And3" |
employmentForm | "FULL" |
employment | "FULL" |
workSchedule | "fullDay" |
workScheduleByDays | ["FIVE_ON_TWO_OFF"] |
workFormats | ["ON_SITE"] |
workingHours | ["HOURS_8"] |
nightShifts | false |
internship | false |
acceptHandicapped | false |
acceptLaborContract | true |
description | "<p>Full HTML description goes here...</p>" |
descriptionText | "Full plain-text description goes here..." |
keySkills | ["Python", "Django", "PostgreSQL"] |
contactInfo.name | "Contact Name" |
contactInfo.email | "contact@example.com" |
contactInfo.phones | [{ "country": "7", "city": "495", "number": "0000000", "formatted": "7 495 0000000" }] |
contactInfo.contactsHidden | false |
professionalRoleIds | [96, 156] |
responsesCount | 42 |
totalResponsesCount | 100 |
onlineUsersCount | 5 |
isAdv | false |
searchUrl | "https://hh.ru/search/vacancy?text=python&area=1&page=0" |
searchSessionId | "00000000-0000-0000-0000-000000000000" |
scrapedAt | "2026-05-05T12:00:00.000Z" |
How to use
Search by keyword + area (recommended)
{"mode": "search","queries": ["python"],"areas": ["1"],"maxPages": 5,"maxListings": 100,"fetchDetails": true}
Search with filters (experience + remote + salary)
{"mode": "search","queries": ["data scientist"],"areas": ["1", "2"],"experience": "between3And6","schedule": ["remote"],"salaryMin": 200000,"onlyWithSalary": true,"orderBy": "salary_desc","maxPages": 10}
URL mode (paste any hh.ru search URL)
{"mode": "url","urls": ["https://hh.ru/search/vacancy?text=AI%20engineer&area=1&experience=between1And3&schedule=remote&page=0"],"maxPages": 5,"fetchDetails": true}
URL mode multi-search
{"mode": "url","urls": ["https://hh.ru/search/vacancy?text=python&area=1&page=0","https://hh.ru/search/vacancy?text=java&area=2&page=0"],"maxPages": 3}
Vacancy mode (scrape specific vacancies by URL or ID)
Hand in an exact list of vacancies you care about and get one full detail card per entry โ no search runs, so hh.ru's 2000-result cap never applies. Accepts full URLs, mobile URLs, or bare numeric IDs (mix freely; duplicates are removed).
{"mode": "vacancy","vacancyInput": ["https://hh.ru/vacancy/123456789","https://m.hh.ru/vacancy/123456790","123456791"]}
Every entry is fetched concurrently and always returns the full card (description, key skills, contact info, logos โ fetchDetails is implied). A removed or archived vacancy returns a record with error: true and code: "VACANCY_UNAVAILABLE" so you can tell exactly which IDs dropped off. maxListings still caps the total; maxPages is ignored in this mode.
A note on the 2000-result limit
hh.ru itself serves at most 2000 results per search filter (40 pages ร 50) โ this is a server-side cap, not a limit of this scraper, and no page count can exceed it. When a search matches more than what's reachable, the run logs a warning telling you so. To capture everything beyond 2000, split one broad search into narrower slices that each stay under the cap, e.g.:
- by area (
["1", "2", "4", ...]instead of["113"]), - by salary band (
salaryMinwindows: 0โ100k, 100โ200k, 200k+), - by professional role or industry,
- or by recency (
orderBy: "publication_time"run on a schedule).
Each slice gets its own fresh 2000-result budget, and results are de-duplicated by vacancyId within a run.
Input parameters
| Field | Type | Default | Description |
|---|---|---|---|
mode | string | search | search, url, or vacancy |
queries | string[] | ["AI"] | Keywords (one search per keyword). Russian fine. |
areas | string[] | ["1"] | Area IDs. 1=Moscow, 2=St Petersburg, 113=Russia. Full list at https://api.hh.ru/areas |
experience | enum | any | any, noExperience, between1And3, between3And6, moreThan6 |
employment | enum[] | [] | Multi: full, part, project, volunteer, probation |
schedule | enum[] | [] | Multi: fullDay, shift, flexible, remote, flyInFlyOut |
salaryMin | integer | (none) | Minimum monthly RUB |
onlyWithSalary | boolean | false | Only listings with a published salary |
orderBy | enum | relevance | relevance, publication_time, salary_desc, salary_asc, distance |
professionalRole | string[] | [] | Numeric role IDs from https://api.hh.ru/professional_roles |
industry | string[] | [] | Numeric industry IDs from https://api.hh.ru/industries |
urls | string[] | (example URL) | Search URLs in URL mode. Filter fields ignored in this mode. |
vacancyInput | string[] | (example) | Vacancy URLs or bare IDs in Vacancy mode. Full card per entry; maxPages ignored. |
maxPages | integer | 5 | 1 to 40 (hh.ru hard cap). Search/URL modes only. |
maxListings | integer | 0 | 0 = unlimited |
fetchDetails | boolean | true | Adds description, keySkills, contact info, full company logos |
proxy | object | Apify default datacenter | Apify Proxy datacenter works fine; Residential RU optional |
Send results into your apps (MCP connectors)
Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape โ the Apify dataset is never changed.
What gets written to the connector: a condensed, human-readable summary of each record โ not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.
- Authorize a connector once under Apify โ Settings โ Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
- For Notion, also set
notionParentPageUrlto the page where items should be created.
The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.
Output example
Sample shape, values are illustrative placeholders, not from a live listing.
{"vacancyId": "100000001","url": "https://hh.ru/vacancy/100000001","name": "Sample Senior Python Developer","publicationDate": "2026-05-05T09:00:00.000+03:00","creationDate": "2026-05-01T09:00:00.000+03:00","lastChangeTime": "2026-05-04T09:00:00.000+03:00","validThroughTime": "2026-06-04T09:00:00.000+03:00","isAdv": false,"searchUrl": "https://hh.ru/search/vacancy?text=python&area=1&page=0","searchSessionId": "00000000-0000-0000-0000-000000000000","company": {"id": 1000000,"name": "Sample Company","visibleName": "Sample Company","isAccreditedIT": true,"isTrusted": true,"category": "COMPANY","state": "APPROVED","siteUrl": "https://www.example.com/","logoUrl": "https://hh.ru/employer-logo-original/0000000.png","logos": [{ "type": "ORIGINAL", "url": "https://hh.ru/employer-logo-original/0000000.png" },{ "type": "vacancyPage", "url": "https://hh.ru/employer-logo/0000000.png" }],"badges": [{ "type": "hrbrand", "description": "Sample badge" }]},"salaryFrom": 200000,"salaryTo": 300000,"salaryCurrency": "RUR","salaryGross": false,"salaryMode": "MONTH","salaryFrequency": "TWICE_PER_MONTH","area": { "id": 1, "name": "ะะพัะบะฒะฐ", "path": ".113.1." },"address": {"city": "ะะพัะบะฒะฐ","street": "Sample Street","building": "1","displayName": "ะะพัะบะฒะฐ, Sample Street, 1","lat": 55.7558,"lng": 37.6173,"metroStations": [{ "id": 1, "name": "Sample Station", "lineColor": "#000000" }],"district": "Sample District"},"workExperience": "between3And6","employment": "FULL","employmentForm": "FULL","workSchedule": "remote","workScheduleByDays": ["FIVE_ON_TWO_OFF"],"workFormats": ["REMOTE"],"workingHours": ["HOURS_8"],"nightShifts": false,"internship": false,"responseLetterRequired": false,"acceptHandicapped": false,"acceptLaborContract": true,"responsesCount": 42,"totalResponsesCount": 100,"onlineUsersCount": 5,"professionalRoleIds": [96, 156],"languages": [{ "id": "eng", "name": "English", "level": "b2" }],"userLabels": [],"description": "<p>Full HTML description text goes here. Includes responsibilities, requirements, and conditions.</p>","descriptionText": "Full plain-text description text goes here. Includes responsibilities, requirements, and conditions.","keySkills": ["Python", "Django", "PostgreSQL", "Docker", "Git"],"contactInfo": {"name": "Contact Name","email": "contact@example.com","phones": [{ "country": "7", "city": "495", "number": "0000000", "comment": null, "formatted": "7 495 0000000" }],"contactsHidden": false},"scrapedAt": "2026-05-05T12:00:00.000Z"}
Plan requirement
- Free Apify plan works. The default proxy is Apify Proxy datacenter, which is included on every plan and passes hh.ru reliably.
- Residential RU is optional. If you want geo-pinned results (e.g. for region-specific salary surveys), pick
Residential+RUin the proxy field. Requires Starter plan or higher. - Pagination cap: hh.ru caps each filter at 2000 vacancies (40 pages of 50). Use multiple
queriesorareasto slice past the cap โ see "A note on the 2000-result limit" above. The run warns you when a search exceeds what's reachable. - maxListings: 0 = unlimited. Bounded only by
maxPagesand the 2000-cap above.
Tips
- Russian keywords work. Pass
"queries": ["ะฟัะพะณัะฐะผะผะธัั"]directly. - Get the latest postings: set
"orderBy": "publication_time"to walk newest-first. - Skip detail pages for speed: set
"fetchDetails": falseto scrape pure SERP data (~30 listings per second). KeepsvacancyId, salary, area, address, company basics, work format, but dropsdescription,keySkills,contactInfo. - Detail coverage at scale: hh.ru rate-limits detail-page requests per IP. The actor detects the rate-limit ("light") page, retries blocked pages with backoff on fresh IPs, and runs a sequential recovery pass โ so large runs keep full descriptions instead of silently dropping them. Every record carries a
detailScrapedboolean, and the run log printsDetail descriptions: X/Y fetched (Z%). If you ever see <100%, re-run with a smallermaxListingsor switch to Residential RU proxy for the best coverage. - Quick fan-out across regions: pass multiple
areas(e.g.["1", "2", "4"]for Moscow + St Petersburg + Novosibirsk) to compare a single keyword across markets.