# India Jobs Scraper - Shine, Internshala, Apna, Cutshort & More (`steadyscrape/india-jobs-scraper`) Actor

Search six India job boards at once (Shine, iimjobs, Hirist, Cutshort, Internshala, Apna): one keyword and city, one table of jobs with company, salary, experience, skills, posted date and full description. Cross-board duplicates removed free. Monitor mode. Export to JSON, CSV or Excel, or via API.

- **URL**: https://apify.com/steadyscrape/india-jobs-scraper.md
- **Developed by:** [Steady Scrape](https://apify.com/steadyscrape) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

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

## India Jobs Scraper — Shine, iimjobs, Hirist, Cutshort, Internshala and Apna in one feed

Scrape **India jobs from six job boards at once** with one search: type a **keyword** and a **city**, and get one table
of jobs from **Shine.com**, **iimjobs.com**, **Hirist.tech**, **Cutshort.io**, **Internshala** and **Apna.co**, all in
the same columns: **title**, **company**, **places**, **salary** (as printed and in rupees), **experience** (as printed
and in years), **work mode**, **skills**, **posted date**, **apply link** and **job link**. Turn on the job page (on by
default) to also get the **full description**, every skill, **openings**, **applicants**, **category**, **industry**
and the **last day to apply**. The same job posted on two boards is delivered **once**, and the copy is free.

No login, no API key, no browser to configure. Unofficial: this Actor is not affiliated with, endorsed or sponsored by
Shine, iimjobs, Hirist, Cutshort, Internshala or Apna.

### What the India jobs feed is for

- **One job search across India's job boards**: tech roles (Hirist, Cutshort), management and finance (iimjobs),
  freshers and early careers (Internshala), blue-collar and entry-level (Apna) and everything (Shine) in one run.
- **Job alerts and job boards**: schedule it with **monitor mode** to receive only the jobs no earlier run delivered.
- **Recruitment and staffing leads**: which companies are hiring for a role in a city right now, on any board.
- **Salary and skills research**: salary ranges in rupees and experience in years, comparable across boards.
- **Datasets for analytics or AI**: thousands of structured India job descriptions with skills attached.

### Input

| Field | What it does |
|---|---|
| **Job titles or skills** | What you would type in a board's search box: `python developer`, `data analyst`, `sales executive`. Each keyword is searched in each city on every board you choose. |
| **Cities** | `Bangalore`, `Pune`, `Mumbai`, `Gurgaon`, `Hyderabad`… Common spellings (`Bengaluru`, `Gurugram`, `New Delhi`) are understood. Empty = all of India. |
| **Job boards** | Any of the six (all by default). A job found on two of them is kept from the one earlier in the list. |
| **Maximum jobs per board and search** | How many jobs to take from each board for each keyword and city (default 20; 0 = every page). |
| **Open each job's page** | One extra page per job for the description and the rest (priced as a job with details). |
| **Only jobs not delivered before** | Monitor mode: skips, for free, every job an earlier run with the same searches delivered, and its copies on other boards. |

```json
{
    "keywords": ["python developer", "data analyst"],
    "locations": ["Bangalore", "Pune"],
    "boards": ["shine", "iimjobs", "hirist", "cutshort", "internshala", "apna"],
    "maxJobsPerBoard": 20,
    "includeDetails": true,
    "onlyNewJobs": false
}
```

### Output: one India job per row, the same columns for every board

Example (with the job page, shortened):

```json
{
    "status": "ok",
    "board": "iimjobs",
    "jobId": "1739956",
    "title": "Sagility - Senior Manager - Company Secretary",
    "company": "SAGILITY INDIA LIMITED",
    "url": "https://www.iimjobs.com/j/sagility-senior-manager-company-secretary-1739956",
    "applyUrl": "https://www.iimjobs.com/j/sagility-senior-manager-company-secretary-1739956",
    "companyLogo": "https://recruiter-static-content.s3.ap-south-1.amazonaws.com/CompanyLogos/centralised-18545.webp",
    "locations": ["Bangalore"],
    "workMode": null,
    "experienceText": "5 - 10 years",
    "experienceMinYears": 5,
    "experienceMaxYears": 10,
    "salaryText": "₹15,00,000 - ₹20,00,000 /year",
    "salaryMin": 1500000,
    "salaryMax": 2000000,
    "salaryCurrency": "INR",
    "salaryPeriod": "year",
    "skills": ["Compliance", "CS", "Regulatory Compliance"],
    "postedAt": "2026-10-15T04:03:01.258Z",
    "postedText": null,
    "search": "company secretary in Bangalore",
    "keyword": "company secretary",
    "location": "Bangalore",
    "position": 1,
    "alsoOn": [],
    "scrapedAt": "2026-10-28T12:00:00.000Z",
    "details": {
        "description": "Board and Committee meetings - India / overseas subsidiaries:\n\n- Preparation of Agenda and…",
        "descriptionHtml": "<p><b>Board and Committee meetings - India / overseas subsid…",
        "skills": ["Compliance", "CS", "Regulatory Compliance", "Legal Jobs in IT/ITeS"],
        "employmentType": null,
        "category": "Legal",
        "industry": "BPO",
        "openings": null,
        "applicants": 34,
        "validThrough": null,
        "companyWebsite": null,
        "companyDescription": null
    }
}
```

| Field | Meaning |
|---|---|
| `status` | `ok` on a job row (the free rows below carry their own status). |
| `board` | `shine`, `iimjobs`, `hirist`, `cutshort`, `internshala` or `apna`. |
| `jobId` / `url` | The board's own id and page for the job. |
| `title` | The job title as the board shows it. |
| `applyUrl` | Where to apply: the employer's own link when the board gives one (iimjobs, Hirist, Apna's careers-site jobs), else the job's page. |
| `company` | As the board shows it; `null` on the few jobs a board lists without one. |
| `companyLogo` | The logo's image link (on Shine, the job's own image when the company has no logo). |
| `locations` | Places as the board writes them (`Bangalore`, `Hinjewadi, Pune`, `Gurgaon/Gurugram`); empty for remote jobs on boards that name no place. |
| `workMode` | `office`, `remote` or `hybrid` (Cutshort's "remote or office" included); `null` when the board does not say. |
| `experienceText` / `experienceMinYears` / `experienceMaxYears` | As printed (`0 to 4 Yrs`, `Min. 2 years`, `No experience required`), and in years; the maximum is `null` when there is none. |
| `salaryText` / `salaryMin` / `salaryMax` / `salaryPeriod` | As printed, and the figures in `salaryCurrency` per `year` or `month` (Apna pays by the month). `null` when the employer hides the salary. |
| `skills` | The skills the board's list shows for the job (Apna's list shows none). |
| `postedAt` / `postedText` | ISO 8601 UTC. Internshala's list shows only an age (`3 days ago`, kept in `postedText`); its job page gives the date, and Apna's the time. |
| `search` / `keyword` / `location` | The search that found the job (`python developer in Bangalore`), its keyword, and its city (`null` for all of India). |
| `position` | The job's place among those its board listed for the search, from 1. |
| `alsoOn` | The same job on other boards in this search (same company, title and city), e.g. a Shine row with `[{ "board": "iimjobs", "jobId": "1723268", "url": "https://www.iimjobs.com/j/data-analyst-risk-financial-markets-1723268" }]`. Those copies are not delivered again and not charged. |
| `scrapedAt` | When the row was made, ISO 8601 UTC. |
| `details` | `null` without the job page, or when that page could not be read (the row is then charged as a plain job). Cutshort's list already carries its description, so its details cost no extra request. |
| `details.description` / `details.descriptionHtml` | The full job description as text and as the board's HTML; empty when the employer wrote none (some Apna jobs list only their tags). |
| `details.skills` | Every skill the job page names. |
| `details.employmentType` / `details.category` / `details.industry` | As the board writes them (`Full Time, Regular`, `Backend Development`, `IT Services & Consulting`); `null` when the board has no such field. |
| `details.openings` / `details.applicants` | Openings and applicants so far, on the boards that show them. |
| `details.validThrough` | The last day to apply, when the board gives one. |
| `details.companyWebsite` / `details.companyDescription` | The employer's website and profile, on the boards that show them (Shine, Cutshort, Internshala). |

A board that gives no job for a search produces one **free** row with `board`, `search`, `keyword`, `location`,
`status`, `reason` and `scrapedAt`, where `status` is `no_results`,
`location_not_found` (a city that board does not list), `not_found` (Cutshort lists jobs by skill and has no list for
the keyword), `blocked` (the board refused to answer) or `unreadable`. The run's `SUMMARY` record lists, per search and
board, the board's own total, jobs delivered, copies found on other boards and jobs skipped by monitor mode.

### Pricing

Pay per result, nothing per run, the same rate as our single-board Actors:

- **US$0.0015 per job** as its board's list shows it (US$1.50 per 1,000).
- **US$0.0025 per job with its own page** (US$2.50 per 1,000).

Copies of a job on other boards, jobs repeated across your searches, jobs skipped by monitor mode, expired Apna jobs
and free rows are never charged. Set a maximum cost per run in Apify and the Actor stops before reading pages it cannot
charge for.

### How each board is searched, and the limits

- **Shine** and **iimjobs / Hirist**: their own keyword search, in their own order, with the city as their location
  filter. iimjobs' search also matches skills, so a tech keyword there can bring finance roles that use that skill.
- **Cutshort** lists jobs by skill (its free-text search is closed to crawlers), so a keyword is matched to its skill
  list: `python developer` reads the Python list. A keyword that names no skill gives a free `not_found` row naming
  similar skills. Cutshort has city lists for 14 cities; any other place is read from the India list.
- **Internshala**: its jobs (not internships) for the keyword in the city.
- **Apna**: its keyword search in the city. Apna's search matches loosely (`python developer` also lists Java and
  WordPress developers), so jobs whose title does not name the keyword's distinctive word are left out, for free.
- Each board is asked at its own polite pace (about one request a second), all six at the same time; with job pages
  most of a run is reading them, one a second or so on each board.
- No recruiter field of any board is read. Phones and e-mails an employer typed into a description, a company name or
  a company profile are replaced by `[phone hidden]` / `[e-mail hidden]`. A name can remain: Shine's consultancies
  sometimes write the hiring person's name into the company name ("… Hiring For <name>"), and a description can name
  a contact person.
- If a board refuses requests, the run stops asking that board, returns what the others gave, and charges nothing
  undelivered.

### Is it legal?

This Actor reads only public job listings that each board shows to any visitor without an account, honours each
board's robots.txt for the pages it reads, and never solves or bypasses a challenge. It collects no personal data
beyond what employers publish with their jobs; a person's name in a company name or a description is still
personal data. Check that your use of the data complies with each board's terms and
the laws that apply to you (such as India's DPDP Act or the GDPR) before using it commercially.

# Actor input Schema

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

One per line, as you would type them in a job board's search box: <code>python developer</code>, <code>data analyst</code>, <code>sales executive</code>. Each keyword is searched in each city below, on every board you choose.

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

One per line: <code>Bangalore</code>, <code>Pune</code>, <code>Mumbai</code>, <code>Gurgaon</code>, <code>Hyderabad</code>. Common spellings such as <code>Bengaluru</code> or <code>Gurugram</code> are understood. A city a board does not list gives a free row explaining why. Leave empty to search all of India.

## `boards` (type: `array`):

Which boards to search. A job found on two of them is kept from the one earlier in this list.

## `maxJobsPerBoard` (type: `integer`):

How many jobs to take from each board for each keyword and city. 0 reads every page a board shows.

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

Adds the full description, every skill, openings, applicants, the last day to apply and the employer's own apply link where a board gives them. Charged as a job with details; a job whose page cannot be read keeps the list's data at the plain price.

## `onlyNewJobs` (type: `boolean`):

For scheduled runs: skips, for free, every job an earlier run with the same keywords, cities and boards delivered, and its copies on other boards.

## Actor input object example

```json
{
  "keywords": [
    "python developer"
  ],
  "locations": [
    "Bangalore"
  ],
  "boards": [
    "shine",
    "iimjobs",
    "hirist",
    "cutshort",
    "internshala",
    "apna"
  ],
  "maxJobsPerBoard": 3,
  "includeDetails": true,
  "onlyNewJobs": false
}
```

# Actor output Schema

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

No description

## `summary` (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 = {
    "keywords": [
        "python developer"
    ],
    "locations": [
        "Bangalore"
    ],
    "boards": [
        "shine",
        "iimjobs",
        "hirist",
        "cutshort",
        "internshala",
        "apna"
    ],
    "maxJobsPerBoard": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadyscrape/india-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 = {
    "keywords": ["python developer"],
    "locations": ["Bangalore"],
    "boards": [
        "shine",
        "iimjobs",
        "hirist",
        "cutshort",
        "internshala",
        "apna",
    ],
    "maxJobsPerBoard": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("steadyscrape/india-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 '{
  "keywords": [
    "python developer"
  ],
  "locations": [
    "Bangalore"
  ],
  "boards": [
    "shine",
    "iimjobs",
    "hirist",
    "cutshort",
    "internshala",
    "apna"
  ],
  "maxJobsPerBoard": 3
}' |
apify call steadyscrape/india-jobs-scraper --silent --output-dataset

```

## MCP server setup

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