# Instahyre Jobs Scraper (`nice_dev/instahyre-jobs-scraper`) Actor

Scrape Instahyre tech jobs in India by keyword, city, skill or company: title, company, experience, skills, recruiter, apply link. Export to JSON, CSV or Excel.

- **URL**: https://apify.com/nice_dev/instahyre-jobs-scraper.md
- **Developed by:** [Nice Dev](https://apify.com/nice_dev) (community)
- **Categories:** Jobs, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.57 / 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.
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

### 💼 What is Instahyre Jobs Scraper?

**Instahyre Jobs Scraper** extracts **tech job listings from [Instahyre](https://www.instahyre.com)**, the Indian hiring platform: **job title, company, skills, locations, remote or not, company size, founding year and badges**, and on request the **full job description, experience asked, posting date, recruiter name and title, agency or direct posting**, and the **company card: website, LinkedIn and social pages, tech stack, benefits and Glassdoor rating**. It works as an **Instahyre API alternative**: run it on a schedule, call it from your code, or plug it into Make, Zapier or n8n.

Type a **skill or job title** (`python`) and a **city** (`Bangalore`), or paste any Instahyre job list, company page or job URL, click **Start**, and download the jobs in JSON, CSV or Excel. No Instahyre account, nothing to set up. From the results list it is **fast: 100 jobs in about 12 seconds, 2,000 jobs in about 3 minutes**, and the **whole site (about 12,800 jobs) can be read in one run**.

### 📋 What data can you extract from Instahyre?

One item per job, 71 fields:

| Category | What you get |
| --- | --- |
| 🏷️ **Job** | title, link, Instahyre job id; with details, still open or closed — `Python Developer` |
| 🏢 **Company** | name, logo, Instahyre company id, tagline, short presentation, founding year, size band, diversity and featured employer badges — `TopDoc`, `0 - 10 employees` |
| 📍 **Location** | cities as listed, every city of the job, work from home, relocation accepted; with details, state and country — `Bangalore`, `Karnataka` |
| 🧰 **Skills and role** | skills asked; with details, job category and job functions — `Python`, `FastAPI`, `Backend Development` |
| 🎓 **Experience and type** | years asked (min, max) and as shown, full time or internship; for internships, the duration and the stipend — `4-8 Years`, `Rs. 10,000 per month` |
| 🕒 **Date** | posting date — `2026-10-21` |
| 📝 **Description** | full job description as text and HTML |
| 👤 **Recruiter** | name, job title and photo of the recruiter who posted the job, the company they work for, posted by an agency or by the employer itself |
| 🏬 **Company card** | Instahyre company page, website, LinkedIn, Facebook, X and Instagram pages, industries, tech stack, headquarters, long presentation, benefits, why join, interview process, office photos, open jobs count, Glassdoor overall rating and sub-ratings |
| ✉️ **Company contacts** (option) | email addresses, kind of the first one (role, generic or personal), the page it was found on, phone numbers and social profiles found on the company's own website |
| 🔎 **Search** | the skill, location and search URL that found the job |

Every field, with an example, is listed in the **Output** section below.

The fields marked **Detail** in that list (description, experience asked, posting date, recruiter, company card…) are filled when **Extract details** is on; the company card's fields are filled too with `enrichEmails` alone, which reads that card once per company. It is off by default: the results list alone already gives title, company, size, badges, skills, cities and remote. Instahyre publishes no salary: only internships show a stipend (the `stipend…` fields).

### ✅ Why use Instahyre Jobs Scraper?

- 📈 **All of Instahyre in one run**: one Instahyre search reaches at most 9,975 jobs; bigger searches are split automatically (by company size, then experience level, then job type), each job returned once.
- 📍 **A real search by city**: `Bangalore`, `Delhi / NCR`, `Work From Home`… and usual spellings (`Bengaluru`, `Gurugram`) are converted; an unknown city stops the run with a clear message instead of returning all of India.
- 🎯 **Every Instahyre filter, by name**: job function, job category, industry, company, company size, job type, years of experience, seniority level, remote only. Pick `Backend Development` or type `Amazon`, no id to look up.
- 🧹 **More filters than Instahyre itself**: posting date range, keywords to include (any or all) or exclude, company name contains or excluded, experience asked, minimum Glassdoor rating, diversity or featured employers only, no agency postings, a cap per company.
- 👤 **Recruiter and agency**: the recruiter's name, title and photo, and whether an agency posted the job for the hiring company.
- 🏬 **Company profile on every row**, and with details the full company card: website, social pages, tech stack, benefits, rating, open jobs.
- ✉️ **Company emails and phones** (option): read on the company's own website, charged only for the companies where an email is found.
- 🔔 **Monitoring built in**: tick **Only new jobs**, schedule the Actor, and each run returns (and charges) only the jobs it has never delivered before.
- 📊 **Market statistics, free** (option): one sheet per search with Instahyre's own counts, per-company figures, and the changes since the previous run.
- 🔌 API, scheduling, integrations (Make, Zapier, n8n, Google Sheets…) and JSON/CSV/Excel export via the Apify platform.

### 🚀 How to scrape Instahyre

1. Create a free Apify account.
2. Open **Instahyre Jobs Scraper**, type a **Skill or job title** (e.g. `python`) and a **Location** (e.g. `Bangalore`), and set the Instahyre filters you want.
3. Or paste your own Instahyre URLs into **Start URLs** (a job list such as `/python-jobs-in-bangalore/`, a search page with its filters, a company page, or single job pages), or job ids into **Job ids**.
4. Set **Max jobs** (100 by default, 0 = no limit) — and **Max jobs per search** when you run several searches — then click **Start**.
5. Download the dataset in JSON, CSV, Excel or via API.

### 💰 How much does it cost to scrape Instahyre?

This Actor uses **pay per event** pricing: you pay for the jobs you get, and the exact prices for your Apify plan are shown in the **Pricing** tab. Platform usage (compute, proxy) is included.

- **`result`**: each job saved from the results list.
- **`result-with-details`**: each job saved with its details (**Extract details** on) — one price for the job, details included, not on top of `result`.
- **`email-enriched`** (option, off by default): once per company and per run where **Email from the company website** finds an email address, on top of the jobs' price; the phone numbers and social links found on the same pages come with it, and a company where no email is found costs nothing.
- **Market statistics** (option): free.
- A small fee per **run start**.
- Filters Instahyre does not offer are applied by the Actor on every job it reads: a job you keep costs its normal price, a job a filter drops costs only a small filter fee (`filter-check`, or `detail-filter-check` when the filter needs the job's details) — filtering never costs more than taking everything. The Instahyre filters of the form are applied by Instahyre itself and cost nothing.

### ⚙️ Input

A search by skill and city:

```json
{
    "query": "python",
    "location": "Bangalore",
    "maxItems": 100
}
```

Several searches with filters and details (2 skills × 2 cities = 4 searches):

```json
{
    "query": "data engineer",
    "searchQueries": ["machine learning"],
    "location": "Pune",
    "locations": ["Hyderabad"],
    "companySize": ["large"],
    "experienceLevel": ["midSenior"],
    "extractDetails": true,
    "postedAfter": "7 days",
    "excludeAgencyPosted": true,
    "maxItems": 200,
    "maxItemsPerQuery": 50
}
```

Instahyre pages pasted as they are:

```json
{
    "startUrls": [
        { "url": "https://www.instahyre.com/python-jobs-in-bangalore/" },
        { "url": "https://www.instahyre.com/jobs-at-big-assets-infra/" }
    ],
    "maxItems": 500
}
```

| Field | Notes |
| --- | --- |
| `startUrls` | Instahyre job lists (`https://www.instahyre.com/python-jobs-in-bangalore/`, `/remote-jobs/`, `/python-internships/`), company pages (`/jobs-at-big-assets-infra/`), search pages (`/search-jobs?skills=python&location=Bangalore`) with their filters, or single job URLs. Pagination is automatic. When set, the search fields are ignored; filters, caps and monitoring still apply. |
| `jobIds` | Instahyre job ids (the number after `/job-` in a job URL: `433344`), read like pasted job URLs. |
| `query`, `searchQueries` | Skill or job title, as typed in Instahyre's "Skills or Title" box: `python`, `react`, `data engineer`. Empty = every job of the location and filters. One search per entry, times each location (max 500 searches per run). |
| `location`, `locations` | City as Instahyre lists it: `Bangalore`, `Mumbai`, `Delhi / NCR`, `Hyderabad`, `Pune`, `Work From Home`, `Anywhere in India`; usual spellings (`Bengaluru`, `Gurugram`) are converted. Empty = all of India and remote. |
| `maxItems` | **Max jobs** (100 by default, 0 = no limit), for the whole run, after deduplication and filters. |
| `maxItemsPerQuery` | Cap for each search, so the first one cannot use up the whole budget (`0` = no cap). |
| `jobFunctions` | Instahyre job functions, from the list of the form (`backend-development`…). Several = any of them. |
| `jobCategories`, `industries` | Broader groups of functions (`data-science-analytics`…) and industries of the hiring company, as Instahyre classifies them. Several = any of them. |
| `companies` | Exact company names as Instahyre shows them (`Amazon`, `Accenture`; case ignored). An unknown name ends its searches at once (no retry) with a clear message naming it; the other searches go on. |
| `companySize`, `jobType`, `experienceYears`, `experienceLevel`, `remoteOnly` | Instahyre's company size groups, full time or internship, your years of experience, seniority levels, Work From Home jobs only. Several sizes or levels = one search each. |
| `extractDetails` | Opens each job: description, experience asked, posting date, recruiter, agency or not, and the company card (once per company per run; if it cannot be read, the job comes out without its company columns). Charged as a job with details (see Pricing). |
| `enrichEmails` | Visits each company's own website (3 pages at most, once per company per run) for its emails, phones and social links. Charged once per company, only when an email is found (see Pricing). |
| `includeMarketStats` | Free. Adds the MARKET_STATS record (Output tab of the run): one sheet per search, see Tips. |
| `postedAfter`, `postedBefore` | Posting date bounds: `2026-09-01`, or a period before now such as `7 days`, `2 weeks`, `1 month`. Need **Extract details** (the date is on the job page only). |
| `includeKeywords`, `keywordMatch`, `excludeKeywords` | Words to keep (`Any` or `All` of them) in the title, company name and skills, with details the description too; words to drop in the title and skills (`intern`). |
| `companyContains`, `excludeCompanies` | Keep or drop the jobs whose company name contains a text: `bank`, `staffing`. |
| `experienceMin`, `experienceMax` | Experience range asked by the job, in years (`5` as a minimum keeps 3-7 and 5-10, drops 0-2). Need **Extract details**. |
| `minCompanyRating`, `diversityEmployersOnly`, `featuredEmployersOnly`, `excludeAgencyPosted`, `maxItemsPerCompany` | Badged employers only, no agency postings, a minimum Glassdoor rating (`4`), at most N jobs per company. The agency and rating filters need **Extract details**. |
| `onlyNew`, `stateKey`, `resetState` | Monitoring: skip the jobs a previous run with the same key (`python-bangalore`) already delivered; reset the memory once to start over. |
| `proxyConfiguration`, `maxConcurrency`, `maxRequestsPerMinute`, `minRequestIntervalMs`, `maxRequestRetries`, `debugLog` | Advanced settings: keep the defaults. |

### 📦 Output

One real job, with **Extract details** on (texts and lists shortened, some columns left out, the option columns empty because **Email from the company website** was off):

```json
{
    "id": "447614",
    "url": "https://www.instahyre.com/job-447614-python-developer/",
    "title": "Python Developer",
    "candidateTitle": "Python Developer",
    "companyName": "TopDoc",
    "companyId": 50756,
    "companyTagline": "A leading technology-enabled healthcare platform",
    "companyFounded": 2000,
    "companySize": "0 - 10 employees",
    "isDiversityEmployer": false,
    "isFeaturedEmployer": false,
    "location": "Bangalore",
    "locations": ["Bangalore"],
    "isRemote": false,
    "acceptOutstation": true,
    "skills": ["Python", "FastAPI", "LLMs", "Agentic AI", "Generative AI"],
    "state": "Karnataka",
    "country": "India",
    "experienceMin": 4,
    "experienceMax": 8,
    "experienceText": "4-8 Years",
    "jobCategory": "Software Engineering",
    "jobFunctions": ["Backend Development"],
    "employmentType": "FULL_TIME",
    "isInternship": false,
    "internshipDuration": null,
    "internshipDurationMonths": null,
    "stipend": null,
    "stipendMin": null,
    "stipendMax": null,
    "stipendCurrency": null,
    "stipendPeriod": null,
    "isActive": true,
    "publishedAt": "2026-10-21",
    "leadScore": 70,
    "leadSignals": ["recruiter", "fresh", "active", "company", "website"],
    "description": "We are looking for a hands-on Python Developer with strong backend development skills…",
    "recruiterName": "Jamila Sakerwala",
    "recruiterDesignation": "Talent Partner",
    "recruiterCompanyName": "Qrata",
    "recruiterPhotoUrl": null,
    "isAgencyPosted": true,
    "companyPageUrl": "https://www.instahyre.com/jobs-at-topdoc/",
    "companyWebsite": "https://topdoc.com/",
    "companyIndustries": ["Computer Software / IT / Internet", "Healthcare / Hospitals"],
    "companyTechStack": ["React.js", "Node.js", "Python", "AWS"],
    "companyHeadquarters": "New York, United States",
    "companyBenefits": [],
    "companyOfficePhotos": [],
    "companyOpenJobs": 6,
    "companyOverallRating": 3.3,
    "companyEmails": [],
    "companyEmailKind": null,
    "companyPhones": [],
    "companySocialLinks": [],
    "searchKeyword": "python",
    "searchLocation": "Bangalore",
    "searchUrl": "https://www.instahyre.com/search-jobs?location=Bangalore&skills=python",
    "scrapedAt": "2026-10-22T04:17:32.757Z"
}
```

Download it as JSON, CSV, Excel, XML or HTML from the **Storage** tab, or through the API. The **Overview** view of the Output tab shows the main columns.

#### All 71 fields

Lists are always present (`[]` when empty); a value Instahyre does not give is `null`. **Detail** = filled with **Extract details** (the `company…` fields of the company card also with `enrichEmails` alone).

| Field | Content |
| --- | --- |
| `id`, `url`, `title`, `candidateTitle` | Instahyre job id (text), job page, title, title as candidates see it |
| `companyName`, `companyId`, `companyLogo`, `companyTagline`, `companyFounded` | Hiring company, its Instahyre id, logo URL, tagline, founding year |
| `companySize`, `companyDescription`, `isDiversityEmployer`, `isFeaturedEmployer` | Size band (`0 - 10` to `More than 1000 employees`), short presentation, Instahyre badges |
| `location`, `locations`, `isRemote`, `acceptOutstation` | Cities as listed and as a list, `Work From Home`, candidates from other cities accepted |
| `skills` | Skills asked |
| `state`, `country` | Detail: state and country of the first location (`null` for most remote jobs; abroad, Instahyre gives no state and the city as country) |
| `experienceMin`, `experienceMax`, `experienceText` | Detail: experience asked in years, and as shown (`4-8 Years`) |
| `jobCategory`, `jobFunctions` | Detail: Instahyre job category and job functions |
| `employmentType`, `isInternship`, `isActive` | Detail: `FULL_TIME` or `INTERN`, internship or not, still open on Instahyre |
| `internshipDuration`, `internshipDurationMonths` | Detail, internships only: length as shown (`6 months`) and in months; `null` for other jobs |
| `stipend`, `stipendMin`, `stipendMax`, `stipendCurrency`, `stipendPeriod` | Detail, internships only: stipend as shown (`Rs. 10,000 per month`, `Unpaid`), its amount, currency (`INR`) and period (`month`); `null` when Instahyre shows none |
| `publishedAt` | Detail: posting date (ISO date) |
| `leadScore`, `leadSignals` | **Lead score** for a recruitment agency, 0 to 100, free and computed from the row's own fields: is the company hiring actively and can it be reached? Points: `direct` 20 (posted by the company, not by an agency), `recruiter` 20 (a named recruiter), `fresh` 20 (published 7 days or less before the run), `active` 10 (job still open), `company` 10 (company named), `featured` 10 (featured employer), `website` 10 (company website known). `direct`, `recruiter`, `fresh` and `active` need **Extract details**, `website` the company card (also read with `enrichEmails`); without them the signal is not counted. `leadSignals` lists the ones the job has. |
| `descriptionHtml`, `description` | Detail: full job description, HTML and plain text |
| `recruiterName`, `recruiterDesignation`, `recruiterCompanyName`, `recruiterPhotoUrl`, `isAgencyPosted` | Detail: recruiter who posted the job, their title, their company, their photo, posted by an agency |
| `companyPageUrl`, `companyWebsite`, `companyLinkedinUrl`, `companyFacebookUrl`, `companyTwitterUrl`, `companyInstagramUrl` | Detail: company page on Instahyre, own website, social pages |
| `companyIndustries`, `companyTechStack`, `companyHeadquarters`, `companyAbout` | Detail: industries, technologies used, headquarters, long presentation |
| `companyBenefits`, `companyWhyJoin`, `companyInterviewProcess`, `companyOfficePhotos`, `companyOpenJobs` | Detail: benefits, "why us" text, interview process, office photos, open jobs on Instahyre |
| `companyOverallRating`, `companyRatings` | Detail: Glassdoor overall rating (1 to 5) and sub-ratings shown on Instahyre; `null` when Instahyre shows none |
| `companyEmails`, `companyEmailKind`, `companyEmailSource`, `companyPhones`, `companySocialLinks` | Option **Email from the company website**: emails, kind of the first one (`role`, `generic`, `personal`), page where it was found, phones, social profiles |
| `searchKeyword`, `searchLocation`, `searchUrl` | The search that found the job (`null` for pasted job URLs and ids) |
| `scrapedAt` | Extraction time (ISO 8601) |

### 💡 Tips

#### How to get more results

Leave **Skill or job title** and **Location** empty and set **Max jobs** to 0: the run reads every job of Instahyre. A search above the 9,975 jobs one Instahyre search reaches is split automatically, by company size, then experience level, then job type, and every job is returned once.

#### How to reduce costs

Leave **Extract details** off when the results list is enough (title, company, skills, cities, remote). Prefer the Instahyre filters of the form (job function, company size, seniority…) to the Actor's own filters: Instahyre applies them before anything is read, at no cost. Cap each search with **Max jobs per search**.

#### Several searches in one run

Every skill of **Skill or job title** and **More skills or titles** is searched in every city of **Location** and **More locations**, up to 500 per run: 3 skills × 4 cities = 12 searches. A job found by several searches is saved once.

#### Monitoring: only the new jobs

Tick **Only new jobs** (`onlyNew`) and schedule the Actor. The first run returns everything; each later run skips the jobs already delivered: they are not saved, not charged and, for the jobs found by a search, their pages are not even opened. The memory lives in a named key-value store of your account (`instahyre-jobs-scraper-seen`, up to 150,000 jobs per key) and is only updated with jobs that really reached the dataset, so a failed run never hides anything. Give each schedule its own `stateKey` (two schedules sharing a key would hide each other's jobs), and tick `resetState` once to start over.

#### Filter by posting date

`postedAfter` and `postedBefore` take a date (`2026-09-01`, the whole day is included, site time zone) or a period before now (`7 days`, `2 weeks`, `1 month`; via the API also a full ISO date-time). They need **Extract details**: Instahyre gives the date on the job page only, so every job of the search is opened to read it. Filtered-out jobs are not saved and do not count in `maxItems` (each job dropped costs the filter fee, see Pricing); the run summary tells how many were filtered.

#### Track companies with market statistics

Tick **Add market statistics** (free): the `MARKET_STATS` record of the run's key-value store gets one sheet per search, with Instahyre's own counts for the whole search (total jobs, company sizes, full time and internships, top functions, industries, companies, cities) and, on the jobs read, per company: jobs, cities, skills, remote share. With the same **Memory key**, each sheet also gives the changes since the previous run: companies new or gone, jobs added or gone per company. Combine it with **Companies (exact names)** to follow a list of employers.

### 🔌 Integrations and API

Call the Actor via the Apify API, the JavaScript or Python clients, or connect it with integrations and webhooks (Make, Zapier, n8n, Google Sheets, Slack, Airtable…). The dataset can be fetched as JSON or CSV from any tool.

### 🤖 Use with AI agents (MCP)

AI agents (Claude, ChatGPT, Cursor…) can find and run this Actor through the [Apify MCP server](https://mcp.apify.com), billed to their Apify account like any run. It returns one item per Instahyre job. Actor id: `nice_dev/instahyre-jobs-scraper`; MCP server with this Actor only: `https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/instahyre-jobs-scraper`.

Smallest input, for a cheap first call:

```json
{
    "query": "python",
    "maxItems": 10
}
```

Key output fields: `url`, `title`, `companyName`, `skills`, `locations`, `isRemote`, `publishedAt` and `description` (with `extractDetails`).

Cost: pay per job (`result`, or `result-with-details` with `extractDetails`) plus a small fee per run start, see the pricing section above. Cap each call with `maxItems` and, through the API, with the run option `maxTotalChargeUsd`.

### ❓ FAQ

#### Is it legal to scrape Instahyre?

The Actor only reads what Instahyre shows publicly to any anonymous visitor. It logs in to nothing. Results can contain personal data — the name, title and photo a recruiter publishes on a job — which is protected by laws such as the GDPR and India's Digital Personal Data Protection Act: do not store it without a legitimate reason. You are responsible for using the data in compliance with Instahyre's Terms of Use and applicable law. This Actor is not affiliated with Instahyre.

#### Does it give the recruiter's email or phone number?

No: Instahyre publishes no email or phone number for its recruiters or companies. The option **Email from the company website** looks for the company's emails, phones and social links on the company's own website, found from its Instahyre card.

#### Does it need a login or a proxy?

No login. The proxy is included in the price: leave the default setting (the residential proxy is not available); without a proxy a large run is much slower. A request the site turns away is retried at once on a new proxy session, up to 10 times on top of the retries (without a proxy, after a pause of 5 seconds, doubled at each retry up to 150 seconds). Instahyre also limits how many jobs one address may open in an hour and in a day: without a proxy, the run waits up to 2 minutes when the site asks; if the site turns the address away for longer, the run stops at once and says for how long. The jobs already saved stay in the dataset (you pay for those only); run it again with the proxy, or later; a resurrected run goes on where it stopped.

#### Is the data safe to open in Excel or to show on a web page?

Titles, descriptions and company texts are the employers' own words, copied as they are. A text can begin with `-`, `+`, `=` or `@`: Excel and Google Sheets may read such a cell of a CSV file as a formula or as a number. The Actor leaves the text as it is, so that the JSON and the API give the real value: when you open a CSV, import these columns as text. Every link, logo and photo field holds an http(s) URL or `null`. `descriptionHtml` is the employer's HTML with its scripts removed and nothing else cleaned: on a web page, sanitize it, and escape every other field like any text written by a stranger.

#### Known limitations

- Instahyre publishes no salary: no salary field is given (internships only: their stipend, when the employer shows it).
- The posting date, description, experience asked, recruiter and company card come from each job's own pages: they are `null` / empty when `extractDetails` is off (the company card is still read with `enrichEmails`), and the date filters and the experience, agency and rating filters need it. If a company card cannot be read, the job still comes out with its own details, without its company columns.
- Instahyre sorts its results by relevance only: there is no "newest first", so a date filter reads every job of the search.
- `companyOverallRating` and `companyRatings` are `null` for the companies that show no Glassdoor rating on Instahyre.
- `onlyNew` remembers job ids, not their content: a job edited since it was delivered is not returned again.
- Two runs sharing the same `stateKey` at the same time may both return the same new job.

**A run that reaches its timeout** stops itself about 45 seconds before it: no new page is asked, what it read is saved and, with `onlyNew`, remembered, and the run ends *Succeeded* with "Stopped before the run's timeout". Resurrect it to go on from there, or give the next run a longer timeout (Run options).

**A run the platform stops without warning** (out of memory)

- Resurrect it: it goes on from where it stood at most a minute before the stop. What it had read since is read again, and the jobs already saved are skipped: none is delivered or charged twice, and `maxItems` still counts them.
- With `onlyNew`, the memory is saved after each write (at most once every 2 seconds): resurrect the stopped run and the jobs it had saved meanwhile join the memory; leave it stopped for good, and the next run may return the jobs of its last 2 seconds once more.

#### Something doesn't work?

The last line of the log counts the jobs saved, filtered out and no longer on Instahyre (removed while the run was reading them), and the requests that failed after every retry. Those requests and the removed jobs are listed, with the reason, in the `FAILED_REQUESTS` record of the run's key-value store. A run that saved nothing and had failed requests fails, and its last message gives the cause. A city Instahyre does not know stops the run before it starts, with a clear message; a company name it does not know ends its searches at once, with a message naming it.

If Instahyre changes its pages, you are told instead of paying for blank rows. A results page that counts jobs but gives none the Actor can read is an error (listed in `FAILED_REQUESTS`), never a quiet "No jobs found". If the first 20 jobs read all lack their title or company name — or, with `extractDetails`, their posting date, description, experience range or recruiter's company — the run saves nothing more, stops and fails, and its last message names the missing field: at most those first jobs are charged. A job that `postedAfter` / `postedBefore` drops because it has no date at all counts among those 20. A run of fewer jobs (a scheduled `onlyNew` run that finds a few new ones, a small **Max jobs**) is checked at its end, from 5 jobs: its jobs are already saved, and the run fails with the missing field instead of ending green.

### 🛟 Support

Open an issue in the **Issues** tab with a link to your run: the run log and the `FAILED_REQUESTS` record of the key-value store show exactly which URLs failed and why.

# Actor input Schema

## `startUrls` (type: `array`):

Instahyre pages: job lists (`https://www.instahyre.com/python-jobs-in-bangalore/`, `/backend-development-jobs/`, `/jobs-in-mumbai/`, `/remote-jobs/`, `/python-internships/`), company pages (`/jobs-at-big-assets-infra/`), search pages (`/search-jobs?skills=python&location=Bangalore`) — keyword, location and filters of the page are kept, pagination is automatic — or single job URLs (`https://www.instahyre.com/job-433344-python-developer-at-big-assets-infra-bangalore/`). When this list is not empty, the search fields below are ignored; filters, caps and monitoring still apply. Max 1 000 URLs. Instahyre filters set below are added to the page's own; when both set the same filter, the page wins.

## `jobIds` (type: `array`):

Instahyre job ids (the number after `/job-` in a job URL: `433344`) to extract directly, like pasting their job URLs. When this list is not empty, the search fields are ignored.

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

What you would type in Instahyre's "Skills or Title" box: a skill (`python`, `react`), a job title (`data engineer`, `product manager`) or a tool. Instahyre matches it on the job's skills and title. Empty = every job of the location and filters.

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

Several skills / titles in one run: one search per entry (times each location). Added to **Skill or job title**; jobs found by several searches are saved once.

## `location` (type: `string`):

City as Instahyre lists it: `Bangalore`, `Mumbai`, `Delhi / NCR`, `Hyderabad`, `Pune`, `Chennai`, `Gurgaon`, `Noida`, `Kolkata`, `Ahmedabad`, `Work From Home`, `Anywhere in India`. Usual spellings (`Bengaluru`, `bangalore`, `Gurugram`, `Delhi`) are converted; a city Instahyre does not know stops the run with a clear message. Empty = all of India and remote.

## `locations` (type: `array`):

Several locations in one run: every keyword is searched in every location (3 keywords × 4 locations = 12 searches, max 500). Added to **Location**.

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

Maximum number of jobs to save for the whole run (after deduplication and filters). 0 = no limit. One Instahyre search reaches at most 9 975 jobs; bigger searches are split automatically (by company size, then experience level, then job type), so the whole site (about 12 800 jobs) can be read in one run.

## `maxItemsPerQuery` (type: `integer`):

Cap for EACH search (skill × location × company size × experience level asked, or pasted URL), so that the first search cannot use up the whole **Max jobs** budget. 0 = no per-search cap.

## `jobFunctions` (type: `array`):

Instahyre job functions (the list of the website's filter). Several = any of them. Empty = all.

## `jobCategories` (type: `array`):

Broader groups of functions (`Software Engineering`, `Sales`…). Several = any of them. Empty = all.

## `industries` (type: `array`):

Industry of the hiring company, as Instahyre classifies it. Several = any of them. Empty = all.

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

Only the jobs of these companies, full names as Instahyre shows them (`Amazon`, `Accenture`, `Big Assets Infra`; case ignored). Combine with an empty skill to get every open job of a company; with **Add market statistics**, each company gets its open-jobs count and the changes since the previous run. A name Instahyre does not know ends its searches at once with a clear message naming it; for part of a name use **Company name contains** below.

## `companySize` (type: `array`):

Instahyre's company size groups. Several = all of them (one search each).

## `jobType` (type: `string`):

Full-time jobs or internships.

## `experienceYears` (type: `integer`):

Your experience in years: Instahyre keeps the jobs open to that experience (`3` → about 4 300 of 12 800 jobs). Empty = all. To bound the range asked by the job itself, use **Experience asked** below.

## `experienceLevel` (type: `array`):

Instahyre's seniority levels. Several = any of them (one search each, jobs found twice saved once). Empty = all.

## `remoteOnly` (type: `boolean`):

Keep only the jobs Instahyre lists as `Work From Home` (also when a city is set: remote jobs of that city's search).

## `extractDetails` (type: `boolean`):

Open each job (2 extra requests per job, plus 1 per company per run): full description (HTML and text), experience asked (min / max), category and functions, recruiter name, title and photo, agency or direct posting, still active, posting date, state, internship duration and stipend, and the company card (website, LinkedIn and social pages, tech stack, industries, headquarters, benefits, why join, interview process, office photos, open jobs count; if the company card cannot be read, the job comes out without its company columns). Charged per job with details (event `result-with-details`, see the pricing). Unticked (default) = the fields of the results list only (faster, cheaper): title, skills, locations, company name, logo, tagline, founded, employees, presentation, diversity and featured badges.

## `enrichEmails` (type: `boolean`):

Visit each company's own website (home, contact and legal pages, 3 pages max, once per company per run; the address comes from the company card on Instahyre, read once per company even without **Extract details**, then 1 small request per job names its company) to find its email addresses, phone numbers and social links. Instahyre itself publishes no email or phone. Charged as a separate event, once per company where an email is found (see Pricing); the phone numbers and social links found on the same pages come with it, and a company where no email is found costs nothing.

## `includeMarketStats` (type: `boolean`):

Free. Adds one record, `MARKET_STATS`, to the run's key-value store (Output tab): one sheet per search with Instahyre's own counts for the whole search (total jobs, by company size, full time / internship, top functions, industries, companies, cities) and, on the jobs read, by company: jobs, cities, skills, remote share (with **Extract details**, also functions and first / last posting date). With the same **Memory key**, each sheet also gives the changes since the previous run: total jobs, companies new or gone, and per company jobs added or gone, cities (with **Extract details**, functions too) started or stopped. No extra request, no charge.

## `postedAfter` (type: `string`):

Only jobs posted on or after this date (`publishedAt`, the posting date of the job page): `2026-09-01`, or a period before now such as `7 days`, `2 weeks`, `1 month` (full ISO date-times work too). Needs **Extract details**: Instahyre gives the date on the job page only (ignored with a warning otherwise).

## `postedBefore` (type: `string`):

Only jobs posted on or before this date (the whole day is included), or older than a period such as `30 days`. Needs **Extract details** (ignored with a warning otherwise).

## `excludeKeywords` (type: `array`):

Drop the jobs whose title or skills contain one of these texts (case and accents ignored). A text inside a longer word counts too: `intern` also drops "International Sales".

## `includeKeywords` (type: `array`):

Keep only the jobs whose title, company name or skills contain these words (case and accents ignored); with **Extract details**, the full description is read too. Empty = all.

## `keywordMatch` (type: `string`):

`Any` keeps a job that contains at least one of the **Include keywords**; `All` only a job that contains every one of them (e.g. all the skills you need).

## `companyContains` (type: `array`):

Keep only the jobs whose company name contains one of these texts (`bank`, `tech`; case and accents ignored). For exact names, **Companies (exact names)** is faster (sent to Instahyre).

## `excludeCompanies` (type: `array`):

Drop the jobs whose company name contains one of these texts (`Accenture`, `staffing`). Case and accents ignored.

## `experienceMin` (type: `integer`):

Keep only the jobs whose experience range reaches this number of years (`5` keeps `3-7` and `5-10`, drops `0-2`). Needs **Extract details** (the range is on the job page; ignored with a warning otherwise). A minimum above the maximum is refused.

## `experienceMax` (type: `integer`):

Keep only the jobs whose experience range starts at or below this number of years (`2` keeps `0-1` and `2-5`, drops `3-7`; `0` = fresher jobs). Needs **Extract details** (ignored with a warning otherwise).

## `diversityEmployersOnly` (type: `boolean`):

Keep only the jobs of companies with Instahyre's diversity employer badge.

## `featuredEmployersOnly` (type: `boolean`):

Keep only the jobs of companies with Instahyre's featured employer badge.

## `excludeAgencyPosted` (type: `boolean`):

Drop the jobs posted by a recruitment agency on behalf of the hiring company (the recruiter works for another company). Needs **Extract details** (ignored with a warning otherwise).

## `minCompanyRating` (type: `number`):

Keep only the jobs of companies whose Glassdoor rating shown on Instahyre (`companyOverallRating`, 1 to 5) is at least this value; companies without a rating are dropped. Needs **Extract details** (the rating is on the company card; ignored with a warning otherwise). Empty = all.

## `maxItemsPerCompany` (type: `integer`):

Keep at most this many jobs of the same company in the run (the first ones read). 0 = no cap.

## `onlyNew` (type: `boolean`):

Skip the jobs that a previous run (same **Memory key**) already delivered: they are not saved and not charged and, for jobs found by a search, their pages are not even opened. First run = everything is new.

## `stateKey` (type: `string`):

Name of the memory used by **Only new jobs** and by the changes of **Add market statistics**. Give each schedule / task its own key (e.g. `python-bangalore`) so that they do not share their memory. Letters, digits, `-` and `_`.

## `resetState` (type: `boolean`):

Forget everything remembered under this **Memory key** before the run: this run returns (and charges) every job again. Untick it afterwards.

## `proxyConfiguration` (type: `object`):

Apify Proxy or your own proxies. Keep the default: it is included in the price, and Instahyre limits each IP address (about 20 results pages a minute, and the job sheets over the hour and over the day), so the Actor spreads the calls over the proxy's addresses. Without a proxy, a large run is slower (a results page every 3 seconds, a job sheet or company card every 5 seconds: about 8 jobs with details a minute), pauses up to 2 minutes when the site asks, and stops when the site refuses the address for longer, keeping what it saved: a large run of job details needs the proxy. The residential Apify proxy is not available in this Actor.

## `maxConcurrency` (type: `integer`):

Maximum number of requests processed in parallel.

## `maxRequestsPerMinute` (type: `integer`):

Most calls to Instahyre in any 60 seconds, every one counted: results pages, job sheets, job pages and company cards (with **Extract details**, a job costs 2 calls, plus 1 per company per run: about 2.5 on average). A budget, not an even pace: up to this many can leave at once when the minute starts (spread them with the minimum delay below). Instahyre itself limits each IP address: about 20 results pages a minute, and the job sheets over the hour and over the day. Without a proxy the Actor spaces them (a results page every 3 seconds, a job sheet or company card every 5 seconds: about 8 jobs with details a minute); after an HTTP 429 the whole run pauses for the delay the site asks, up to 2 minutes, then goes on — a longer delay stops the run, with what it saved kept (a large run of job details needs the proxy); behind the proxy each new session is a new address.

## `minRequestIntervalMs` (type: `integer`):

Smallest gap between two requests, in milliseconds. Unlike the per-minute rate, this spreads the requests evenly instead of letting them go out in a burst. 0 = no gap.

## `maxRequestRetries` (type: `integer`):

Retries per request before it is marked as failed. Behind a proxy, a request the site turns away is also retried on a new proxy session up to 10 times without using up these retries.

## `debugLog` (type: `boolean`):

Include debug messages in the run log.

## Actor input object example

```json
{
  "startUrls": [],
  "jobIds": [],
  "query": "python",
  "searchQueries": [],
  "location": "Bangalore",
  "locations": [],
  "maxItems": 100,
  "maxItemsPerQuery": 0,
  "jobFunctions": [],
  "jobCategories": [],
  "industries": [],
  "companies": [],
  "companySize": [],
  "jobType": "any",
  "experienceLevel": [],
  "remoteOnly": false,
  "extractDetails": false,
  "enrichEmails": false,
  "includeMarketStats": false,
  "excludeKeywords": [],
  "includeKeywords": [],
  "keywordMatch": "any",
  "companyContains": [],
  "excludeCompanies": [],
  "diversityEmployersOnly": false,
  "featuredEmployersOnly": false,
  "excludeAgencyPosted": false,
  "maxItemsPerCompany": 0,
  "onlyNew": false,
  "stateKey": "default",
  "resetState": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxConcurrency": 8,
  "maxRequestsPerMinute": 120,
  "minRequestIntervalMs": 0,
  "maxRequestRetries": 5,
  "debugLog": false
}
```

# Actor output Schema

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

No description

## `marketStats` (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 = {
    "query": "python",
    "location": "Bangalore",
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("nice_dev/instahyre-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 = {
    "query": "python",
    "location": "Bangalore",
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("nice_dev/instahyre-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 '{
  "query": "python",
  "location": "Bangalore",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call nice_dev/instahyre-jobs-scraper --silent --output-dataset

```

## MCP server setup

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