# Naukri Jobs Scraper - Full Descriptions & Applicant Counts (`solidscripting/naukri-scraper`) Actor

Scrape Naukri.com job listings across India by keyword and city. Title, company, AmbitionBox rating, experience, salary, skills and the complete job description - plus applicant and view counts no other Naukri scraper publishes. Remote and salary filters, CSV/JSON/Excel export.

- **URL**: https://apify.com/solidscripting/naukri-scraper.md
- **Developed by:** [Alwin](https://apify.com/solidscripting) (community)
- **Categories:** Jobs, Business, Lead generation
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.30 / 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

## Naukri Jobs Scraper — scrape Naukri.com job listings from India

Get structured job data from **Naukri.com**, India's largest job portal, by keyword
and city. Every listing comes back with the employer's **AmbitionBox rating**, the
**experience range**, **parsed skills** and a **job description** — and optionally,
where Naukri serves it, **how many people have already applied**.

No login, no Naukri account, no API key. Export to **JSON, CSV or Excel**, or pull it
straight from the Apify API.

***

### What this scraper gets you

| | |
|---|---|
| **Job** | title, absolute URL, posted date (real ISO timestamp), vacancies, walk-in flag |
| **Company** | name, Naukri careers page, logo, **AmbitionBox employee rating**, reviews link |
| **Money** | salary band, currency, and an explicit `salaryDisclosed` flag |
| **Fit** | experience range (parsed to min/max), skills as a clean list, location |
| **Demand** ⭐ | **applicant count** and **view count** per listing |
| **Context** ⭐ | full description, industry, functional area, role category, education, company profile |

⭐ = included when `fullDescription` is enabled.

**Applicant counts turn a job board into a demand signal.** In a 10-row Mumbai
data-analyst run the median listing had **2,186 applicants and 5,196 views**, and the
most contested — Data Analyst at ICICI Lombard — had **7,913 applicants**. That changes
what you do with a posting, whether you are a jobseeker deciding where to spend effort,
a recruiter pricing a role, or an analyst measuring real demand rather than counting
adverts.

> **`fullDescription` is off by default** because it visits each job's own page and
> so takes longer. Coverage is complete when it runs — the last measured platform run
> enriched 20 of 20 — and `descriptionIsFull` marks each row either way, so a rare
> miss is always visible rather than silent. The run completes regardless, and every
> row still ships with its full search-level data.

***

### Quick start

```json
{
  "keyword": "python developer",
  "location": "bangalore",
  "maxItems": 100
}
```

Several roles and cities in one run:

```json
{
  "keywords": ["data analyst", "business analyst"],
  "locations": ["bangalore", "mumbai", "pune"],
  "maxItems": 600,
  "workMode": "remote"
}
```

That's 6 searches. They run **interleaved**, so stopping at `maxItems` leaves you with
every combination covered instead of 600 rows from one city. De-duplication is global —
a job listed in three cities is stored, and billed, once. Every row carries
`searchKeyword` and `searchLocation` so you always know which search produced it.

***

### Input

| field | default | what it does |
|---|---|---|
| `keyword` | `python developer` | job title, skill or keyword |
| `location` | `bangalore` | Indian city; blank searches all of India |
| `keywords` | — | several keywords at once; overrides `keyword` |
| `locations` | — | several cities at once; overrides `location` |
| `maxItems` | `50` | exact stop — you get the number you asked for |
| `fullDescription` | `false` | complete description + applicant/view counts (slower) |
| `daysOld` | — | only jobs posted in the last N days |
| `experience` | — | years of experience |
| `workMode` | — | `remote`, `hybrid` or `office` |
| `salaryBand` | — | `0to3` … `75to100`, lakhs per annum |
| `maxPages` | `200` | per-search safety cap |
| `proxyConfiguration` | RESIDENTIAL | Naukri is behind Akamai; residential is the safe default |

#### Filters that actually filter

Each one was measured against a known baseline of **11,276** jobs
(python developer / Bangalore) before it was exposed:

| filter | result |
|---|---|
| `experience` 0 / 3 / 8 | 339 / 3,884 / 6,364 |
| `daysOld` 1 / 3 / 7 / 15 | 352 / 899 / 1,819 / 3,781 |
| `salaryBand` 0to3 / 3to6 / 6to10 | 862 / 3,926 / 6,373 |
| `workMode: remote` | every returned row's location reads `Remote` |

Naukri also publishes an employment-type facet and a role-category facet. Both were
tested; both return the unfiltered count. They are **deliberately not offered here** —
a filter that silently ignores you is worse than no filter.

***

### Output

```json
{
  "jobId": "240826007480",
  "title": "Python Software Developer",
  "url": "https://www.naukri.com/job-listings-python-software-developer-capgemini-...",
  "companyName": "Capgemini",
  "companyRating": "3.6",
  "companyReviewsUrl": "https://www.ambitionbox.com/reviews/capgemini-reviews",
  "location": "Hybrid - Hyderabad, Pune, Bengaluru",
  "experienceText": "6-11 Yrs",
  "minimumExperience": "6",
  "maximumExperience": "11",
  "salaryText": "Not disclosed",
  "salaryDisclosed": false,
  "skills": ["API", "Python", "Rest", "Django", "Cloud", "Fast API"],
  "postedAt": "2026-09-21T11:37:26+00:00",
  "vacancies": 6,
  "applyCount": 2493,
  "viewCount": 7423,
  "industry": "IT Services & Consulting",
  "employmentType": "Full Time, Permanent",
  "educationUG": ["Any Graduate"]
}
```

47 fields per row. Detail-only fields are always present — `null` when
`fullDescription` is off — so the column set never changes between runs.

***

### Two honest notes before you buy

**Most Indian listings do not publish a salary.** That is the market, not the scraper.
Disclosure ran **11%** in a Bangalore python-developer sample and **27%** in a Mumbai
data-analyst one. `salaryDisclosed` tells you which is which, and `minimumSalary` /
`maximumSalary` are `null` rather than `0` when hidden, so you can never mistake a
hidden salary for a free job. For India, `skills` and `experienceText` carry more
signal than salary does.

**The fast description is not always the complete one.** Without `fullDescription`
you get Naukri's search-result text: 72 to 4,579 characters in a 45-row sample,
**median 363**, and one row held only 3.8% of what its job page showed. Turn
`fullDescription` on and the same field runs to a **median of 3,111 characters** —
an 8.6× lift — on a platform run that enriched 20 of 20. `descriptionIsFull` marks
each row, so you always know which you got.

***

### How it works

Naukri server-renders nothing. Its search page ships an empty `"jobDetails":[]` shell
and the browser then calls a JSON API sitting behind **Akamai Bot Manager**, which
answers `406 recaptcha required` to anything that cannot prove it is a real browser.

So this actor runs a real Chromium **once** to let Naukri's own JavaScript mint a
request token, then replays that token over plain HTTP for about 40 further
requests — roughly **800 jobs per browser launch**. You pay for one page load per ~800
jobs instead of one per page. Measured: 20 jobs per request, ~3.5 KB per job,
1,587 jobs in 47 seconds.

***

### Pricing

| | |
|---|---|
| **Result** | **$0.30 / 1,000** — every job row |
| **Full job details** | **$1.70 / 1,000** — only when `fullDescription` is on, and only for jobs actually enriched |
| Actor start | $0.002, once per run |

Platform usage is included — you are not billed separately for compute. A run that
returns nothing costs you only the start fee.

Leave `fullDescription` off and you pay $0.30/1,000, which is the cheapest rate for
Naukri on the Store. Turn it on and an enriched row is $2.00/1,000 all in. Jobs that
come back without their detail fields are **not** charged the detail rate, so a page
Naukri declines to serve costs you nothing extra.

***

### FAQ

**Do I need a Naukri account or login?**
No. Everything here is public job-listing data.

**How many jobs can I get from one search?**
Naukri caps each query's result set — a typical city+keyword search reports 11,000+
jobs. Use several `locations`, or narrow with `daysOld`, to reach further overall.

**Can I get only remote jobs?**
Yes — set `workMode` to `remote`. Verified: every returned row's location reads
`Remote`.

**Why is `salaryDisclosed` false on most rows?**
Because most Indian employers hide the salary on Naukri. See the note above.

**Can I schedule this?**
Yes. Use Apify Schedules, or the API, and filter with `daysOld: 1` to pull only what
was posted since your last run.

**Does it work for all of India?**
Yes. Leave `location` blank for a nationwide search, or name any city —
Bangalore, Mumbai, Delhi NCR, Hyderabad, Pune, Chennai, Kolkata, Noida, Gurgaon,
Ahmedabad and the rest.

**What if Naukri rate-limits my run?**
The run ends **successfully** with a status message explaining it, rather than
failing — so a rate-limited minute never looks like a broken actor. Re-run shortly
after.

***

### Limits

- **Page size is fixed at 20 and must not be raised.** Naukri treats its page-size
  parameter as advisory: it will cap a response to 20 rows while still advancing the
  offset by the number you asked for, so requesting 100 and getting 20 silently
  discards 80 jobs per page while the output looks perfectly healthy. This actor
  never does that.
- Naukri's own reported total is unreliable under the `workMode` filter — it reported
  32,403 against an 11,276 baseline — so it is never used as a stopping condition.

### Legal

This scrapes publicly visible job listings. It does not log in, bypass authentication,
or collect candidate profiles or personal data. You are responsible for how you use
the output, including under the GDPR and Naukri's terms.

# Actor input Schema

## `keyword` (type: `string`):

Job title, skill or keyword, e.g. "python developer", "data analyst", "sales manager".

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

Indian city, e.g. "bangalore", "mumbai", "delhi ncr", "pune". Leave blank to search all of India.

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

Several job titles or skills at once. Crossed with every location and interleaved, so a run that hits the limit has covered every combination. Overrides the single Search keyword field when set.

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

Several Indian cities at once. Crossed with every keyword. Overrides the single Location field when set.

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

Stop after this many job records. Pages are fetched automatically (20 jobs per page).

## `fullDescription` (type: `boolean`):

Fetch each job's own page data. Adds the COMPLETE description (measured 12.7x longer than the search snippet) plus applyCount, viewCount, employment type, industry, role, education requirements, split preferred/other skills and a company profile. Costs one extra request per job, so expect the run to take notably longer.

## `daysOld` (type: `integer`):

Only return jobs posted within this many days. Leave blank for all.

## `experience` (type: `integer`):

Filter to jobs matching this many years of experience. Leave blank for all.

## `workMode` (type: `string`):

Filter to remote, hybrid, or on-site roles. Verified against returned rows: 'remote' yields listings whose location reads Remote.

## `salaryBand` (type: `string`):

Naukri's own salary facet, in lakhs per annum (INR). Note most Indian listings do not disclose a salary at all; this filters to the ones that do within the band.

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

Hard cap on result pages. Usually leave as is.

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

Naukri is fronted by Akamai Bot Manager. RESIDENTIAL is the safe default; datacenter may work but is not guaranteed.

## Actor input object example

```json
{
  "keyword": "python developer",
  "location": "bangalore",
  "keywords": [
    "python developer",
    "data analyst"
  ],
  "locations": [
    "bangalore",
    "pune",
    "mumbai"
  ],
  "maxItems": 50,
  "fullDescription": false,
  "maxPages": 200,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

The scraped Naukri job listings (one item per job).

# 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 = {
    "keyword": "python developer",
    "location": "bangalore",
    "keywords": [
        "python developer",
        "data analyst"
    ],
    "locations": [
        "bangalore",
        "pune",
        "mumbai"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("solidscripting/naukri-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 = {
    "keyword": "python developer",
    "location": "bangalore",
    "keywords": [
        "python developer",
        "data analyst",
    ],
    "locations": [
        "bangalore",
        "pune",
        "mumbai",
    ],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("solidscripting/naukri-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 '{
  "keyword": "python developer",
  "location": "bangalore",
  "keywords": [
    "python developer",
    "data analyst"
  ],
  "locations": [
    "bangalore",
    "pune",
    "mumbai"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call solidscripting/naukri-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,solidscripting/naukri-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/9WA7nqi6tbYpcm9Ro/builds/fqgfVf2guR7PwfvbY/openapi.json
