# Instahyre Scraper (`mlg14/instahyre-scraper`) Actor

Scrape public Instahyre jobs and company hiring counts. Export roles, skills, locations, employer details, descriptions, experience ranges, and recruiter information.

- **URL**: https://apify.com/mlg14/instahyre-scraper.md
- **Developed by:** [MLG Data](https://apify.com/mlg14) (community)
- **Categories:** Jobs, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Instahyre Scraper

Scrape Instahyre jobs, employer context, skills, locations, and optional public job details. Export Instahyre job data to CSV, JSON, or Excel for hiring research, job boards, and recurring market snapshots. This actor provides an Instahyre API alternative with structured results and a company hiring-count mode.

The actor reads public job listings. A standard run writes one row per job. Company mode writes one hiring profile per requested employer. No account or candidate profile is needed.

### What data can you extract from Instahyre?

The search feed supplies role and employer fields. Turning on detail fetching adds the description, experience requirements, category, and public recruiter fields. Values are left empty when the source does not publish them.

| Field | Description | Example |
| --- | --- | --- |
| `recordType` | Row kind | `job` |
| `jobId` | Stable public role identifier | `432410` |
| `title` | Published job title | `Senior Engineering Manager` |
| `candidateTitle` | Alternate title shown to candidates | `Senior Engineering Manager` |
| `companyName` | Hiring employer name | A published employer name |
| `companyId` | Public employer identifier | `20943` |
| `companyResourceUri` | Employer resource path | `/api/v1/candidate_opportunity_employer/20943` |
| `companyLogoUrl` | Public employer logo link | A media URL |
| `companyTagline` | Public employer tagline | A short statement |
| `companyFounded` | Employer founding year, if present | `1868` |
| `employeeCount` | Employer size value from the source | `1000` |
| `companyNote` | Public employer profile summary | A short paragraph |
| `isDiversityEmployer` | Public diversity badge flag | `false` |
| `isFeaturedEmployer` | Public featured badge flag | `false` |
| `locations` | Split location labels | `["Bangalore"]` |
| `locationsRaw` | Original location label | `Bangalore` |
| `isRemote` | Whether the location explicitly says remote or work from home | `false` |
| `skills` | Published skill tags | `["Architecture", "Python"]` |
| `acceptOutstation` | Whether outstation applicants are accepted | `true` |
| `publicUrl` | Public job page | A job URL |
| `resourceUri` | Source job record path | `/api/v1/job_search/432410` |
| `description` | Plain text from the public detail description | A job description |
| `experienceMin`, `experienceMax` | Experience range in years | `10`, `14` |
| `jobCategory` | Published category | `Software Engineering` |
| `jobFunctions` | Published function labels | `["Backend Development"]` |
| `jobType` | Full-time role or internship | `full_time` |
| `recruiterName` | Public recruiter name | A profile name |
| `recruiterDesignation` | Recruiter role | A designation |
| `recruiterProfileUrl` | Public recruiter image link | A media URL |
| `recruiterCompanyName` | Recruiter's listed organization | A published name |
| `isAgencyPosted` | Whether that organization differs from the hiring employer | `true` |
| `agencyFunctionNames` | Functions covered by an agency recruiter | `["Backend Development"]` |
| `detailStatus`, `detailError` | Detail fetch result or a short failure reason | `ok` |
| `found` | Exact employer found in company mode | `true` |
| `openRoles` | Public count for a tracked employer | `185` |
| `functionBreakdown` | Top public function counts in company mode | A name-to-count object |
| `locationBreakdown` | Top public location counts in company mode | A location-to-count object |
| `warning` | Reason a company was not confirmed | A short message |
| `changeType` | Snapshot, new, updated, unchanged, or confirmed removed | `unchanged` |
| `firstSeenAt`, `lastSeenAt` | UTC observation times; retained across monitoring runs | ISO timestamps |
| `openRolesDelta` | Change in a tracked employer count since its last run | `4` |
| `functionsStarted`, `functionsStopped` | Changes among top function facets | A label array |
| `locationsOpened`, `locationsClosed` | Changes among top location facets | A label array |
| `firstTrackedAt`, `lastTrackedAt` | UTC observation times for a tracked employer | ISO timestamps |
| `source` | Source domain | `instahyre.com` |
| `scrapedAt` | UTC collection time | An ISO timestamp |

The optional details belong to each public job, not to a private candidate account. The recruiter fields are public listing metadata. The actor does not invent salary or posting dates when those are absent from the source.

### How to scrape Instahyre

1. Choose a job function or leave the function list empty to scan the general public feed.
2. Add any job type, employer size, skill, keyword, location, company, or remote filters you need.
3. Set `maxItems` and `maxPages`. Start with 35 results and two source pages while testing a new search.
4. Enable `includeDetails` when descriptions, experience, and recruiter fields are needed.
5. Run the actor and download the default dataset as JSON, CSV, or Excel.

To get a hiring count for named employers, enter their exact published names in `trackCompanies`. That switches the output to company profiles. Other search filters are ignored in that mode.

### Input

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `jobFunctionSlugs` | string array | `[]` | Live public function slugs. Unknown slugs fail with a clear error. |
| `jobType` | enum | `any` | Any, full-time, or internship. |
| `companySize` | enum | `any` | Small, medium, large, or any. |
| `skills` | string array | `[]` | Match published skill tags. A single skill is also sent to the source filter. |
| `skillMatch` | enum | `any` | Match any or all requested skills. |
| `keywords` | string array | `[]` | Terms matched against role, employer, skill, and location text. |
| `keywordMatch` | enum | `any` | Match any or all requested keywords. |
| `locations` | string array | `[]` | Match public location labels. |
| `remoteOnly` | boolean | `false` | Keep explicitly remote roles. |
| `companyNames` | string array | `[]` | Match employer names. One name also narrows the source request. |
| `excludeKeywords` | string array | `[]` | Exclude rows containing any listed term. |
| `diversityEmployersOnly` | boolean | `false` | Keep employers with the public diversity badge. |
| `includeDetails` | boolean | `false` | Fetch a public detail record per candidate job. |
| `excludeAgencyPosted` | boolean | `false` | Skip agency-posted roles; requires details. |
| `trackCompanies` | string array | `[]` | Return hiring-count profiles instead of jobs. |
| `monitorMode` | enum | `snapshot` | Current rows or changes since a complete prior scan. |
| `emitBaseline` | boolean | `true` | Emit all rows on the first monitoring run. |
| `includeUnchanged` | boolean | `false` | Include unchanged rows in monitoring output. |
| `stateName` | string | Empty | Optional stable name for a comparison state. |
| `maxItems` | integer | `50` | Maximum rows saved to the dataset. |
| `maxPages` | integer | `10` | Maximum public search pages read. |
| `proxyConfiguration` | object | Enabled | Proxy routing for source requests. |

Example input for a focused job search:

```json
{
  "jobFunctionSlugs": ["backend-development"],
  "skills": ["Python"],
  "jobType": "full_time",
  "maxItems": 35,
  "maxPages": 3,
  "includeDetails": true
}
```

The function slug is resolved against the current public taxonomy before search. The actor uses the source's job-function identifier, so an obsolete slug stops with an error instead of silently returning unrelated jobs. For several skills, the requested match rule is applied to the returned skill tags. Keywords, remote flags, and exclusion terms are checked on each row after retrieval.

### Output example

This shortened item comes from a successful 35-job validation run. Employer identity and links are omitted from the excerpt; they are present in the saved dataset.

```json
{
  "recordType": "job",
  "jobId": "432410",
  "title": "Senior Engineering Manager",
  "candidateTitle": "Senior Engineering Manager",
  "locations": ["Bangalore"],
  "locationsRaw": "Bangalore",
  "isRemote": false,
  "acceptOutstation": true,
  "companyFounded": 1868,
  "employeeCount": 1000,
  "isDiversityEmployer": false,
  "isFeaturedEmployer": false,
  "source": "instahyre.com"
}
```

A successful detail-enabled validation run saved 35 rows. `jobId`, `title`, `companyName`, `locationsRaw`, `skills`, `publicUrl`, `description`, `jobCategory`, and `detailStatus` were populated in every row.

Company mode produces rows with `recordType` set to `company_profile`. Its `openRoles` value comes from the public search count for the requested name. The function and location breakdowns contain the top categories returned with that search. They are not a complete breakdown of every function and city.

### Use cases

- **Job-board coverage:** add current India-focused technology and business roles to a searchable feed with stable identifiers for deduplication.
- **Recruiting research:** inspect the skills and locations associated with a function before writing outreach or sourcing plans.
- **Employer watchlists:** request hiring counts for exact employer names on a schedule, then compare the rows across runs in your own database.
- **Location analysis:** measure which public listings mention a city or explicitly advertise remote work within a defined search slice.
- **Role enrichment:** add descriptions and experience ranges to a saved set of jobs when titles and skill tags are insufficient.
- **Agency review:** use public recruiter organization fields to identify roles that appear to be posted by an agency.

Each saved job has a stable `jobId`. Store that ID when combining several searches so overlapping roles are counted once. A repeated search may include the same role because the public feed reflects currently active listings rather than a historical stream.

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

The configured result price is **$0.001 per saved row, or $1 per 1,000 results**. A 35-row run corresponds to $0.035 in result charges; 500 rows correspond to $0.50; 2,000 rows correspond to $2.00. These examples use the configured result rate and exclude any separate account-level usage or proxy charges that may apply to your plan.

`maxItems` limits how many rows are saved and charged. Filtering can require the actor to scan more source rows than it saves. Detail fetching adds a source request per candidate role, so it can increase run time and infrastructure usage even when the saved-row count is the same. Company mode saves one row per requested company, subject to `maxItems`.

The actor writes a `MARKET_SNAPSHOT` record to its run's key-value store. It contains the public total job count for the final search page, top companies and locations, function counts, company-size counts, scanned-row count, and whether the page scan reached the end. This record is separate from the dataset rows.

### Tips for best results

Start with a source-backed filter such as `jobFunctionSlugs`, `jobType`, or `companySize`. They reduce the source count before local matching. A single skill and a single company name also narrow the source request. When a single company name returns no exact-filter results, the actor scans the broader feed and applies the name locally.

Increase `maxPages` when local filters are selective. A remote-only search, for example, may need many source pages to find 50 matching jobs. The source accepts a requested limit but caps each page at 35 jobs; the actor follows the actual cap when advancing offsets. Ten pages can inspect up to 350 distinct rows before local filters are applied.

Leave `includeDetails` off for a fast overview. Turn it on for text descriptions, experience ranges, categories, and recruiter fields. Detail failures leave the base job row in the dataset with `detailStatus` set to `failed` and a short `detailError`. This makes a partial detail outage visible without discarding the search result.

Use an exact employer name for company profiles. The public company filter may treat partial names broadly. The actor confirms an exact match among the first 35 returned jobs before reporting that employer's count. If it cannot confirm a match there, `found` is false and `warning` explains the limitation. Repeated company runs use a persistent state to report `openRolesDelta` and changes among the top function and location facets.

### Limits

The public feed is a current listing source. It does not consistently provide a posting date, salary, or a historical record of removed jobs. Monitoring compares collected snapshots rather than claiming a source posting date. Choose `changes_only` and keep the same `stateName` for repeated runs. A role is marked removed only after it is absent from two complete scans. Capped or incomplete scans do not advance the comparison state.

The search API caps each page at 35 jobs. `maxPages` is a safety cap, so a broad query can stop before the source's complete inventory has been scanned. `MARKET_SNAPSHOT.sourcePagesComplete` reports whether the scan reached the end. Reaching `maxItems` can also stop a scan early. The snapshot's public total is the source's count for its search filter; it is not the final count after local keyword, location, or remote checks.

Employer, description, recruiter, and skill fields reflect what the source currently exposes. Some may be absent or change without notice. Remote detection requires an explicit remote-style phrase in the location label; it does not infer remote work from the job description. The agency flag compares the public recruiter organization with the hiring employer name, which is a useful signal but can be affected by naming differences.

Source availability, rate limits, and proxy behavior can vary. Requests start through the configured proxy route; the shared fetch layer retries blocked requests and can escalate its proxy group when a challenge persists. Repeated access limits may slow or interrupt a run. There is no login flow, private candidate data, or access to application records.

### Automation prompts

Use a short, explicit instruction when creating a recurring search:

> Collect up to 35 backend-development jobs with Python in the skill tags. Include public detail records and save the dataset as JSON.

For an employer watchlist:

> Return hiring-count profiles for these exact published employer names and compare their counts with the previous run.

These examples describe inputs the actor accepts. Persistent comparison state is kept under the selected state name.

### FAQ

#### Is it legal to collect these jobs?

The actor reads public listing records without logging in. Follow the site's terms, applicable privacy law, and your own data-retention rules. Do not use recruiter details for unwanted contact or collect private candidate information.

#### Do I need to set a proxy?

The input enables proxy routing by default. You can supply a different supported proxy configuration if your account requires it. A blocked request can trigger retries and a proxy escalation, which may affect account usage.

#### How fast is a run?

The validated 35-job search completed successfully. Larger searches depend on the number of pages, filter selectivity, and whether details are enabled. Detail mode makes one additional public request for each candidate job, so it usually takes longer than a list-only run.

#### Can I schedule a run to monitor hiring?

Yes. Select `changes_only`, keep the same filters and `stateName`, and schedule repeated runs. The first run can emit the baseline as new rows. Later complete scans emit new and updated roles; unchanged rows are optional. Removal requires absence from two complete scans. Company mode reports hiring-count changes from its previous run.

#### Can I export results to a spreadsheet?

Yes. Download the default dataset in CSV or Excel format, or connect its dataset endpoint to a spreadsheet workflow. Arrays such as `skills` and `locations` may be serialized as cell text in tabular exports.

#### Why is a field empty?

The public source may not publish that value. Description, experience, recruiter, and agency fields appear only when `includeDetails` is enabled and the detail request succeeds. A failed detail request leaves the list row intact with a visible status.

#### Why did a filtered run return fewer rows than `maxItems`?

`maxItems` is a ceiling. The public source may have fewer matching jobs, or local filters may reject many scanned rows before `maxPages` is reached. Raise `maxPages`, choose a broader source filter, or relax keyword and location terms.

### Integrations

Use the dataset endpoint in an application, scheduled data pipeline, webhook workflow, or spreadsheet import. Stable job IDs help with deduplication and snapshot comparisons. A named monitoring state supports recurring change reports. The per-run `MARKET_SNAPSHOT` record gives the source's high-level counts alongside the exported rows.

### Support

Open an issue on the Issues tab with the input that produced the problem and a short description of the expected fields. Include the run ID when reporting an incomplete or blocked scan.

# Actor input Schema

## `jobFunctionSlugs` (type: `array`):

Live function slugs from the public taxonomy; empty searches all functions.

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

Search all jobs, full-time roles, or internships.

## `companySize` (type: `string`):

Filter by the public employer size group.

## `skills` (type: `array`):

Match skill tags published for each role.

## `keywords` (type: `array`):

Match title, company, skills, or location text.

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

Match published location text.

## `companyNames` (type: `array`):

Match employer names; one name is also sent to the source filter.

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

Omit roles matching any term in title, company, skills, or location.

## `skillMatch` (type: `string`):

Require any or all requested terms.

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

Require any or all requested terms.

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

Keep roles with an explicit remote or work-from-home label.

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

Keep roles whose public employer record carries the diversity badge.

## `includeDetails` (type: `boolean`):

Add public description, experience range, category, recruiter, and agency fields. Adds a request per saved candidate role.

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

Omit jobs whose recruiter company differs from the hiring employer. Requires detail fetching.

## `trackCompanies` (type: `array`):

Alternative mode: output one public hiring-count profile per exact employer name. Search filters are ignored.

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

Maximum dataset rows to save.

## `maxPages` (type: `integer`):

Maximum public search pages to scan; the source caps each page at 35 jobs.

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

Proxy settings for public source requests.

## `monitorMode` (type: `string`):

Snapshot returns current jobs. Changes only compares complete scans in a persistent named state.

## `emitBaseline` (type: `boolean`):

In changes-only mode, emit the first complete search as new rows.

## `includeUnchanged` (type: `boolean`):

In changes-only mode, include rows whose public fields did not change.

## `stateName` (type: `string`):

Optional stable name for the persistent comparison state; use separate names for separate searches.

## Actor input object example

```json
{
  "jobFunctionSlugs": [],
  "jobType": "any",
  "companySize": "any",
  "skills": [],
  "keywords": [],
  "locations": [],
  "companyNames": [],
  "excludeKeywords": [],
  "skillMatch": "any",
  "keywordMatch": "any",
  "remoteOnly": false,
  "diversityEmployersOnly": false,
  "includeDetails": false,
  "excludeAgencyPosted": false,
  "trackCompanies": [],
  "maxItems": 50,
  "maxPages": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "monitorMode": "snapshot",
  "emitBaseline": true,
  "includeUnchanged": false,
  "stateName": ""
}
```

# Actor output Schema

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

Public jobs or company hiring profiles in the default dataset.

# 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 = {
    "jobFunctionSlugs": [],
    "jobType": "any",
    "companySize": "any",
    "skills": [],
    "keywords": [],
    "locations": [],
    "companyNames": [],
    "excludeKeywords": [],
    "skillMatch": "any",
    "keywordMatch": "any",
    "remoteOnly": false,
    "diversityEmployersOnly": false,
    "includeDetails": false,
    "excludeAgencyPosted": false,
    "trackCompanies": [],
    "maxItems": 50,
    "maxPages": 10,
    "proxyConfiguration": {
        "useApifyProxy": true
    },
    "monitorMode": "snapshot",
    "emitBaseline": true,
    "includeUnchanged": false,
    "stateName": ""
};

// Run the Actor and wait for it to finish
const run = await client.actor("mlg14/instahyre-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 = {
    "jobFunctionSlugs": [],
    "jobType": "any",
    "companySize": "any",
    "skills": [],
    "keywords": [],
    "locations": [],
    "companyNames": [],
    "excludeKeywords": [],
    "skillMatch": "any",
    "keywordMatch": "any",
    "remoteOnly": False,
    "diversityEmployersOnly": False,
    "includeDetails": False,
    "excludeAgencyPosted": False,
    "trackCompanies": [],
    "maxItems": 50,
    "maxPages": 10,
    "proxyConfiguration": { "useApifyProxy": True },
    "monitorMode": "snapshot",
    "emitBaseline": True,
    "includeUnchanged": False,
    "stateName": "",
}

# Run the Actor and wait for it to finish
run = client.actor("mlg14/instahyre-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 '{
  "jobFunctionSlugs": [],
  "jobType": "any",
  "companySize": "any",
  "skills": [],
  "keywords": [],
  "locations": [],
  "companyNames": [],
  "excludeKeywords": [],
  "skillMatch": "any",
  "keywordMatch": "any",
  "remoteOnly": false,
  "diversityEmployersOnly": false,
  "includeDetails": false,
  "excludeAgencyPosted": false,
  "trackCompanies": [],
  "maxItems": 50,
  "maxPages": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "monitorMode": "snapshot",
  "emitBaseline": true,
  "includeUnchanged": false,
  "stateName": ""
}' |
apify call mlg14/instahyre-scraper --silent --output-dataset

```

## MCP server setup

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