# Naukri Jobs Scraper — India Job Listings (`leadsbrary/naukri-jobs-scraper`) Actor

A naukri jobs scraper that turns Naukri.com job searches into structured data: title, company, salary range, experience, skills, location, posted date and job URL. Export to JSON, CSV or Excel. From $0.22 per 1,000 results.

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

## Pricing

from $0.22 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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

## Naukri Jobs Scraper — India Job Listings to JSON/CSV/Excel

A **naukri jobs scraper** that turns any Naukri.com job search into a clean, structured dataset: job title, company, salary range, experience band, skills, location, posted date and the canonical job URL. Export straight to JSON, CSV or Excel, or pull results over the Apify API. From $0.22 per 1,000 results.

### What it does

The Actor queries naukri.com's public job-search pages for the keywords, locations and filters you give it. A plain HTTP request to Naukri's search API is blocked by an Akamai bot check, so the Actor drives a fingerprinted headless browser and reads the same JSON response (`jobapi/v3/search`) the site's own page already loads — no HTML/DOM scraping. Listings are deduplicated by Naukri's own job ID and one dataset row is delivered per unique job. Only data naukri.com already shows to any visitor without logging in is collected — no login, no candidate profiles, no recruiter dashboard, and no recruiter emails or phone numbers.

### Who it's for

- **Recruiters and staffing agencies** sourcing India-market openings and finding companies actively hiring for a role/city.
- **Job-board and aggregator builders** who need a reliable, scheduled Naukri feed.
- **HR and market-research teams** tracking hiring volume, salary bands and in-demand skills by keyword, location and experience level.
- **Competitive hiring intelligence** teams monitoring what roles specific companies advertise publicly.

### Use Cases

- **Sourcing pipelines**: pull every current Naukri listing for a role and city combination (e.g. "data engineer" in Bangalore) directly into an ATS or spreadsheet, refreshed on a daily schedule.
- **Salary benchmarking**: aggregate the normalised `salary` object across hundreds of listings for a skill or seniority band to see real, currently-advertised pay ranges.
- **Skill-demand tracking**: tally the `skills` array across a keyword's results over time to spot which technologies are trending up or down in India hiring.
- **Competitor hiring monitoring**: point `startUrls` at a specific company's Naukri *search-results* page (e.g. its "jobs at \<company>" listing page, not an individual job-detail URL) to track what roles and locations they're actively recruiting for.
- **Incremental job feeds**: combine `onlyNewSince` with a schedule to power a job board or Slack/email alert that only surfaces newly posted listings, never re-billing duplicates.

### Features

- Search by **keywords**, **location**, **experience**, **posted-within-days** and **minimum salary**, or pass Naukri **start URLs** directly.
- Normalised **salary object** (`min`, `max`, `currency`, `period`, `raw`) instead of a raw string — `min`/`max`/`period` are `null` and only `raw` is kept when Naukri shows a salary label but no parseable number.
- **Deterministic dedup** by `jobId`, so duplicates across pages or keywords are never billed.
- **Incremental mode** (`onlyNewSince`) — scheduled runs only bill genuinely new listings.
- **`maxResults` always enforced** — a run can never overspend, even if the query matches thousands of jobs.
- Optional **full job-description fetch** (`includeJobDescription`) for detail-page text, job type and applicant count.
- Pay only for delivered, deduplicated results — no charge for empty or over-filtered queries.

### Input

| Field | Type | Required | Description |
|---|---|---|---|
| `keywords` | array of strings | No | Job titles, skills or free-text queries. Each is searched separately. |
| `location` | array of strings | No | City/region filter (e.g. `bangalore`, `delhi-ncr`). Empty = all India. |
| `startUrls` | array of objects | No | Naukri search-*results* page URLs to process directly (not individual job-detail URLs — those are not intercepted). Only `naukri.com` hosts accepted. |
| `experienceYears` | integer | No | Minimum years of experience (0–30). |
| `postedWithinDays` | integer | No | Only jobs posted in the last N days (1, 3, 7, 15, 30). |
| `salaryMinLakhs` | integer | No | Minimum annual salary in INR lakhs, per Naukri's own facets. |
| `includeJobDescription` | boolean | No | Fetch each job's detail page for full description text. Slower and more expensive per result. Default `false`. |
| `onlyNewSince` | ISO 8601 date-time | No | Incremental mode: skip listings older than this timestamp. |
| `maxResults` | integer | **Yes** | Hard cap on delivered results (and spend). Default `20`. |
| `proxyConfiguration` | object | No | Apify Proxy settings. Defaults to the standard Apify Proxy pool. |

At least one of `keywords` or `startUrls` must be supplied.

### Output

Each dataset row is one job listing:

| Field | Type | Description |
|---|---|---|
| `jobId` | string | Naukri's own job identifier (used for dedup). |
| `title` | string | Job title as published. |
| `company` | string | Hiring company or consultancy name. |
| `companyUrl` | string | null | Naukri company profile URL, if linked. |
| `companyRating` | number | null | Company rating (0–5) if shown. |
| `location` | array\<string> | Work locations, split by city. |
| `experienceMinYears` / `experienceMaxYears` | number | null | Required experience range. |
| `salary` | object | null | `{ min, max, currency, period, raw }`; `null` when "Not disclosed". `min`/`max`/`period` are `null` (with `raw` kept) when Naukri shows a label it can't parse to a number. |
| `skills` | array\<string> | Skill tags on the job card. |
| `jobType` | string | null | e.g. Full Time, Internship. Only populated when `includeJobDescription` is true; otherwise `null`. |
| `workMode` | string | null | e.g. Hybrid, Remote, Work from office. |
| `postedAt` | string | null | ISO 8601 UTC timestamp derived from the relative label. |
| `postedAtRaw` | string | null | The original relative label (e.g. "3 Days Ago"). |
| `description` | string | null | Card teaser, or full text when `includeJobDescription` is true. |
| `openings` | integer | null | Number of openings, if published. |
| `applicantCount` | integer | null | Number of applicants, if publicly shown. Only populated when `includeJobDescription` is true; otherwise `null`. |
| `url` | string | Canonical public job URL. |
| `searchKeyword` | string | null | The input keyword that produced this result. |
| `scrapedAt` | string | ISO 8601 UTC extraction timestamp. |

Sample record (from an actual production run):

```json
{
  "jobId": "180926016268",
  "title": "PySpark Data Engineer",
  "company": "Infosys",
  "companyUrl": "https://www.naukri.com/infosys-jobs-careers-11244",
  "companyRating": 3.5,
  "location": ["Hyderabad", "Chennai", "Bengaluru"],
  "experienceMinYears": 2,
  "experienceMaxYears": 5,
  "salary": null,
  "skills": ["Pyspark", "Spark", "SQL", "Apache Spark", "Hive", "Data Engineering", "Hadoop", "Big Data"],
  "jobType": null,
  "workMode": null,
  "postedAt": "2026-09-19T00:00:00.000Z",
  "postedAtRaw": "10 Days Ago",
  "description": "Preferred Candidate Profile Exposure to Databricks,Hadoop,or Hive is preferred 2-5 years of experience in Data Engineering Strong hands-on experience with PySpark and Apache Spark Good SQL knowledge Experience in ETL and Big Data technologies",
  "openings": 20,
  "applicantCount": null,
  "url": "https://www.naukri.com/job-listings-pyspark-data-engineer-infosys-hyderabad-chennai-bengaluru-2-to-5-years-180926016268",
  "searchKeyword": "data engineer",
  "scrapedAt": "2026-09-29T05:09:28.434Z"
}
```

`salary` is `null` here because this listing did not disclose a salary; when Naukri does publish one, you get a normalised `{ min, max, currency, period, raw }` object.

### How to use it via the API

#### curl

```bash
curl "https://api.apify.com/v2/acts/YOUR_USERNAME~naukri-jobs-scraper/run-sync-get-dataset-items?token=YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "keywords": ["data engineer"],
    "location": ["bangalore"],
    "maxResults": 50
  }'
```

#### JavaScript (apify-client)

```javascript
import { ApifyClient } from "apify-client";

const client = new ApifyClient({ token: "YOUR_API_TOKEN" });

const run = await client.actor("YOUR_USERNAME/naukri-jobs-scraper").call({
  keywords: ["data engineer"],
  location: ["bangalore"],
  postedWithinDays: 7,
  maxResults: 200,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python (apify-client)

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")

run = client.actor("YOUR_USERNAME/naukri-jobs-scraper").call(run_input={
    "keywords": ["data engineer"],
    "location": ["bangalore"],
    "includeJobDescription": True,
    "postedWithinDays": None,
    "maxResults": 200,
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

### Pricing

Pay-per-event: **$0.22 per 1,000 results** on the GOLD tier (result = one delivered, deduplicated job listing). This undercuts the cheapest credible comparable ($0.27/1,000) by 18.5%.

| Tier | Price per 1,000 results |
|---|---|
| FREE | $0.33 |
| BRONZE | $0.29 |
| SILVER | $0.25 |
| GOLD / PLATINUM / DIAMOND | $0.22 |

`maxResults` always caps spend, and duplicate or failed items are never billed.

### Troubleshooting

- **0 results returned**: your keyword/location/filter combination may not match any current Naukri listing. The run still succeeds with an explicit log line — try a broader keyword or drop a filter.
- **`startUrls` rejected**: only `naukri.com` URLs are accepted; other hosts fail validation before any request is made.
- **`startUrls` returns 0 items**: only search-*results* page URLs are supported (e.g. `.../data-engineer-jobs-in-bangalore`); an individual job-detail URL loads a different API and is not intercepted.
- **`salary` is `null`**: the listing itself says "Not disclosed" — no salary was published at all.
- **`salary.min`/`max`/`period` are `null` but `salary.raw` has a value**: Naukri showed a salary label (e.g. a text range) that couldn't be parsed to a number; the original label is kept in `raw`.
- **Slow runs with `includeJobDescription`**: each result needs an extra detail-page fetch; if a detail fetch fails after retries, the listing is still delivered using the shorter description already captured from the search page, rather than dropped.
- **Fewer items than `maxResults`**: Naukri search caps the number of result pages per query; the Actor stops cleanly and logs how many were available.

### FAQ

**Does this require a Naukri account or login?**
No. It only reads public search and job-listing pages that any visitor can see without signing in.

**Does it collect recruiter emails, phone numbers or candidate data?**
No. Only employer-published listing fields are collected — no personal contact data.

**Can I run it on a schedule and only get new jobs?**
Yes — set `onlyNewSince` to the timestamp of your last run to skip already-seen listings.

**Why is `salary.min`/`max` sometimes `null` even though the listing looks like it has a number?**
Naukri publishes salary in inconsistent formats (Lacs PA, per-month, ranges). When a listing's label can't be normalised into a number, `min`/`max`/`period` stay `null` rather than showing a guessed number, but the original label is preserved in `salary.raw`. `salary` itself is only `null` when no salary was published at all.

**Is this data allowed to be collected?**
This Actor reads only publicly visible, unauthenticated pages, paces requests through Apify Proxy, and reuses naukri.com's own public search endpoints. You are the data controller for anything you retain and are responsible for your own lawful basis and for honouring deletion requests.

### Keywords

naukri jobs scraper, naukri job scraper, naukri.com scraper, scrape naukri jobs, naukri job listings api, india jobs scraper, india job board scraper, naukri jobs api, job scraper india, naukri job data export, indian job listings dataset, recruitment data scraper india, job postings scraper, naukri salary data, hiring data india

### Hashtags

\#naukri #jobscraper #jobs #india #recruiting #hrtech #jobboard #webscraping #leadgeneration #dataextraction #apify #jobsapi

# Changelog

This Actor's version history is a separate document: https://apify.com/leadsbrary/naukri-jobs-scraper/changelog.md

# Actor input Schema

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

Job titles, skills or free-text queries to search on Naukri. Each keyword is searched separately.

## `location` (type: `array`):

City or region filter as used by Naukri search (e.g. bangalore, delhi-ncr). Empty means all India.

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

Optional Naukri search-results page URLs to process directly, instead of keywords/location (individual job-detail URLs are not supported). Only naukri.com URLs are accepted.

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

Minimum years of experience filter (0-30). Leave empty for no filter.

## `postedWithinDays` (type: `integer`):

Freshness filter: only jobs posted within the last N days (Naukri supports 1, 3, 7, 15, 30). Leave empty for no filter.

## `salaryMinLakhs` (type: `integer`):

Minimum annual salary filter in INR lakhs, mapped to Naukri's own salary facet buckets. Leave empty for no filter.

## `includeJobDescription` (type: `boolean`):

Fetch each job's detail page to add the full description text, employment type and applicant count. Slower and one extra page load per result.

## `onlyNewSince` (type: `string`):

Skip listings whose posted date is older than this ISO 8601 timestamp, so scheduled runs only bill new jobs.

## `maxResults` (type: `integer`):

Hard cap on delivered results across all keywords; also caps spending.

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

Naukri blocks unfingerprinted/datacenter-heavy traffic; Apify Proxy is recommended. Select a residential-friendly group your account has access to if the default pool gets blocked.

## Actor input object example

```json
{
  "keywords": [
    "data engineer"
  ],
  "location": [
    "bangalore"
  ],
  "startUrls": [],
  "includeJobDescription": false,
  "maxResults": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (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": [
        "data engineer"
    ],
    "location": [
        "bangalore"
    ],
    "maxResults": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("leadsbrary/naukri-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": ["data engineer"],
    "location": ["bangalore"],
    "maxResults": 20,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("leadsbrary/naukri-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": [
    "data engineer"
  ],
  "location": [
    "bangalore"
  ],
  "maxResults": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call leadsbrary/naukri-jobs-scraper --silent --output-dataset

```

## MCP server setup

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