# Naukri Jobs Scraper — India + Gulf, drop-in compatible (`diopside/naukri-jobs`) Actor

Drop-in for valig/naukri-jobs-scraper and muhammetakkurtt/naukri-job-scraper — both input and output vocabularies in one actor. Public job listings from Naukri.com (India) and NaukriGulf.com: title, company, location, salary, experience, skills, apply link, UTC posted-at.

- **URL**: https://apify.com/diopside/naukri-jobs.md
- **Developed by:** [DIOPSIDE AI](https://apify.com/diopside) (community)
- **Categories:** Jobs, Business, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 job listings

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 — India + Gulf

**Drop-in compatible with `valig/naukri-jobs-scraper` *and* `muhammetakkurtt/naukri-job-scraper` — both input vocabularies, both output vocabularies, both job boards, one actor.** Public job listings from Naukri.com (India) and NaukriGulf.com (UAE, Saudi Arabia, Qatar, Egypt and the rest of MENA), as clean JSON. No login, no proxy, no browser.

Switching from either incumbent means changing the actor id. Nothing else.

***

### Why this one

The Naukri cluster is crowded and the leaders work. This actor is not here to fix a broken scraper; it is here to remove the three things that cost you time once the data is in your warehouse.

**1. One actor instead of two.** `valig` emits nested records (`id`, `url`, `company{}`, `salary{}`, `experience{}`, `skills{}`, `description{}`, `locations[]`). `muhammetakkurtt` emits flat ones (`jobId`, `jdURL`, `companyName`, `salaryDetail{}`, `experienceText`, `tagsAndSkills`, `jobDescription`, `location`). Both vocabularies are in every record here, side by side, so whichever one your code already parses keeps working. Their *input* field names both work too — `keyword` and `keywords`, `maxJobs` and `limit`, `freshness` and `jobAge`, `workMode: ["remote"]` and `wfhType: ["2"]`, `sortBy: "date"` and `sort: "f"`.

**2. Timestamps you can actually sort on.** Naukri's own API dates a search result in UTC, dates the same posting's job page in IST, sometimes sends that field as a formatted string and sometimes as a bare epoch — and labels none of it. Every record here carries **`postedAt`**, one ISO-8601 UTC timestamp, plus `postedDaysAgo`. Naukri's original strings are kept beside it in `createdDateText` so you can check the work.

**3. Salary you can filter on.** Most Indian postings hide the salary, and both boards will happily tell you the salary is visible while carrying no number — Naukri zeroes the figures, NaukriGulf sends `IsCtcHidden: "false"` with the CTC fields empty. `salaryDisclosed` is true only when there is a real number to read, and `salaryMinLpa` / `salaryMaxLpa` give it in lakh per annum instead of raw rupees.

And one thing you will hopefully never notice: **the filters you asked for are checked against the postings that come back before anything is pushed.** Both Naukri APIs answer `200` with a plausible-looking payload when a parameter name is not the one they expect — ask NaukriGulf for `query=python&location=dubai` in the obvious lower-case spelling and you get 39,410 unrelated jobs and no error at all. If a whole page of results contradicts a filter you set, the run fails loudly instead of billing you for the wrong data. (`verifyFilters: false` turns this off.)

### Input

| Field | Type | Notes |
|---|---|---|
| `jobBoard` | `"naukri"` | `"naukrigulf"` | Default `naukri`. A start URL picks its own board, so one run can mix both. |
| `keyword` | string | Skills, designation or company. Alias: **`keywords`**. |
| `location` | string | `Bangalore`, `Pune`, `Dubai`, `Saudi Arabia`... |
| `searchUrl` | string | Paste a naukri.com / naukrigulf.com search URL. Its query string is carried through, so filters with no field below still work. |
| `startUrls` | array | Several search URLs and/or individual job URLs. |
| `jobIds` | array | 12-digit job ids or full job URLs; skips search entirely. |
| `maxJobs` | integer | Default 100, `0` for everything. Alias: **`limit`**. |
| `fetchDetails` | boolean | Full description, role, industry, department, education, view/apply counts, company address. Default off for Naukri.com, **on for NaukriGulf**, whose search results carry no description at all. |
| `outputFormat` | `"normalized"` | `"raw"` | `raw` emits the API record exactly as `muhammetakkurtt/naukri-job-scraper` does. |
| `verifyFilters` | boolean | Default `true`. See above. |
| `sortBy` | `"relevance"` | `"date"` | Alias: **`sort`** (`"r"` / `"f"`). |
| `experience` | string / integer | Years, or `"all"`. |
| `freshness` | `"1"`–`"30"` | Days. Alias: **`jobAge`**. |
| `workMode` | array | `office`, `remote`, `hybrid`. Alias: **`wfhType`** (`"0"`, `"2"`, `"3"`). |
| `postedBy` | array | `"1"` company, `"2"` consultant. Alias: **`jobPostType`**. |
| `cities`, `department`, `industry`, `roleCategory`, `role`, `companyType`, `salaryRange`, `topCompanies`, `ugCourse`, `pgCourse`, `employmentType`, `walkin`, `walkinDate` | arrays / booleans | Naukri.com id filters. Every record carries the ids it matched (`locations[].gId`, `roleCategoryGid`), so one run tells you the values to use next. |
| `country`, `gulfCity`, `gulfIndustry`, `gulfFunctionalArea`, `gulfSalaryRange`, `nationality`, `gender`, `language` | arrays / string | NaukriGulf cluster filters. |
| `urlParam` | key/value list | Passed straight to the search API. Repeat a key to mean "both of these". |
| `proxyConfiguration` | object | **Off by default** — Naukri answers Apify's egress directly. |
| `residentialFallback` | boolean | Default `true`: if the configured tier ever gets blocked, retry once on residential in-country (IN / AE) rather than failing. A healthy run never pays residential bandwidth. |

### Output

One record per posting. Abridged, from a live run:

```json
{
  "jobId": "210926001708",
  "id": "210926001708",
  "jobBoard": "naukri",
  "title": "Python Developer",
  "url": "https://www.naukri.com/job-listings-python-developer-tata-consultancy-services-pune-chennai-bengaluru-4-to-8-years-210926001708",
  "jdURL": "https://www.naukri.com/job-listings-python-developer-...-210926001708",
  "companyName": "Tata Consultancy Services",
  "company": {
    "id": 892542, "name": "Tata Consultancy Services",
    "jobsUrl": "https://www.naukri.com/tata-consultancy-services-jobs-careers-13542",
    "overviewUrl": "https://www.naukri.com/tata-consultancy-services-overview-223346",
    "address": "Gachibowli, Rangareddy Hyderabad, Telangana, India"
  },
  "location": "Pune, Chennai, Bengaluru",
  "locations": [{ "gId": "97", "label": "Pune", "url": "https://www.naukri.com/jobs-in-pune" }],
  "workMode": "office",
  "experienceText": "4-8 Yrs",
  "experience": { "text": "4-8 Yrs", "minimum": "4", "maximum": "8" },
  "salaryDisclosed": false,
  "salaryMinLpa": null,
  "salaryMaxLpa": null,
  "salaryDetail": { "minimumSalary": 0, "maximumSalary": 0, "currency": "INR", "hideSalary": true },
  "tagsAndSkills": "Pandas,Pytest,Numpy,Python",
  "skills": { "preferred": ["Pandas", "Pytest", "Numpy", "Python"], "other": ["Data Handling", "Github"] },
  "jobDescription": "<p>Required Technical Skill Set ...</p>",
  "description": { "full": "<p>Required Technical Skill Set ...</p>", "short": "4+ years Python development ..." },
  "postedAt": "2026-09-21T04:24:45Z",
  "postedDaysAgo": 0,
  "createdDate": 1789964685000,
  "createdDateText": "2026-09-21 04:24:45",
  "role": "Software Development - Other",
  "roleCategory": "Software Development",
  "industry": "IT Services & Consulting",
  "department": "Engineering - Software & QA",
  "employmentType": "Full Time, Permanent",
  "education": { "ug": ["Any Graduate"], "pg": [], "ppg": [] },
  "vacancy": 10,
  "viewCount": 162,
  "applyCount": 102,
  "companyRating": 3.2,
  "totalResults": 1929,
  "searchPage": 1,
  "position": 1,
  "hasDetails": true
}
```

`role`, `industry`, `department`, `education`, `viewCount`, `applyCount`, the company address and the full `jobDescription` need `fetchDetails: true`. `hasDetails` tells you per record whether the job page was read, so an absent field is never ambiguous.

**Public job listings only.** Nothing about candidates, applicants or recruiters is collected. `nationality` and `gender` reflect preferences the employer published on the advert itself.

### Switching from an incumbent

**From `valig/naukri-jobs-scraper`** — change the actor id. `keywords`, `location`, `sort`, `jobAge`, `wfhType`, `experience`, `jobPostType`, `limit` and `urlParam` all keep working, and the nested `id`/`url`/`company`/`salary`/`experience`/`skills`/`description`/`locations` fields are in every record. Set `fetchDetails: true` to match their depth (they always read the job page).

**From `muhammetakkurtt/naukri-job-scraper`** — change the actor id. `jobBoard`, `keyword`, `searchUrl`, `jobIds`, `maxJobs`, `fetchDetails`, `sortBy`, `experience`, `freshness`, `workMode`, `cities`, `department`, `salaryRange`, `companyType`, `roleCategory`, `role`, `walkin`, `walkinDate`, `ugCourse`, `pgCourse`, `postedBy`, `industry`, `topCompanies`, `location`, `language`, `nationality`, `country`, `gulfCity`, `gulfIndustry`, `gulfFunctionalArea`, `gulfSalaryRange` and `gender` are all accepted. Set `outputFormat: "raw"` for their exact record shape, or leave it on `normalized` to get their field names plus everything else.

Two differences worth knowing: `maxJobs` here has no 50-job minimum, and `outputFormat: "raw"` applies to search results — a `jobIds` fetch always returns the normalized record, which contains a superset of the same information.

### Sizes, speed and cost

Measured on the platform, 1 GB, no proxy:

| Run | Records | Time | Requests |
|---|---|---|---|
| Naukri.com, keyword + location + freshness, `fetchDetails: true` | 40 | 20 s | 43 |
| NaukriGulf, keyword + location, details on | 30 | 12 s | 31 |
| Naukri.com canary, 25 jobs with details | 25 | 14 s | 28 |

Naukri.com pages 20 results at a time and NaukriGulf 30; `fetchDetails` adds one request per posting. NaukriGulf stops paginating at 45,000 results, which the run reports rather than looping.

### Use cases

- Job-market tracking: titles, skills, experience bands and salary distributions by city, role category or industry, over time.
- Recruitment intelligence: which employers are hiring for what, at what seniority, with `applyCount` and `vacancy` as demand signals.
- Salary benchmarking on the minority of postings that publish numbers — `salaryDisclosed` gets you that subset in one filter.
- Job-board and aggregator feeds: `postedAt` plus `freshness: "1"` gives a clean daily delta.
- Skill-demand analysis from `tagsAndSkills` / `skills.preferred`.

### Notes on reliability

- Everything that changes is discovered at run time; no build ids or tokens are hardcoded.
- Duplicate postings across pages are dropped, so 100 records means 100 distinct jobs. Naukri's relevance ordering repeats results between pages more often than you would expect.
- A failed job-page fetch costs that posting its detail fields, never the record.
- Partial failures are reported in the run's status message. The run only fails when nothing at all was produced.
- You are charged once per pushed job, and never for a posting that was not written to the dataset.

# Actor input Schema

## `jobBoard` (type: `string`):

Which site to scrape. 'Naukri.com' targets India; 'NaukriGulf.com' targets the Gulf/MENA region (UAE, Saudi Arabia, Qatar, ...). A start URL or job URL picks its own board, so one run can mix the two.

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

Skills, designation or company to search for. Alias: `keywords`.

## `keywords` (type: `string`):

Same as `keyword` — accepted so input written for valig/naukri-jobs-scraper works unchanged.

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

City or region. On Naukri.com any Indian city ('Bangalore', 'Pune'); on NaukriGulf any Gulf/MENA city or country ('Dubai', 'Saudi Arabia').

## `searchUrl` (type: `string`):

Paste a naukri.com or naukrigulf.com search-results URL to use instead of the typed filters. Its query string is carried through to the API, so any filter the site supports works here even if it has no field below.

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

Several search URLs and/or individual job URLs in one run.

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

Fetch specific postings directly by their 12-digit job id or full job URL (naukri.com or naukrigulf.com — the id is extracted). Skips search entirely.

## `maxJobs` (type: `integer`):

How many job records to return in total. 0 means every result. Alias: `limit`.

## `limit` (type: `integer`):

Same as `maxJobs` — accepted so input written for valig/naukri-jobs-scraper works unchanged.

## `fetchDetails` (type: `boolean`):

Also open each posting's job page for the full description, role, industry, department, education, view/apply counts and company address. Defaults to off for Naukri.com and on for NaukriGulf, whose search results carry no description at all.

## `outputFormat` (type: `string`):

'Normalized' carries both incumbents' field names side by side plus the derived fields. 'Raw' emits the API record exactly as muhammetakkurtt/naukri-job-scraper does, for buyers switching from it who parse those keys.

## `verifyFilters` (type: `boolean`):

Check the returned postings against the filters asked for, and fail the search rather than push results if the API ignored one. Both Naukri APIs answer 200 with an unfiltered feed when a parameter is not the one they expect.

## `sortBy` (type: `string`):

Relevance or newest first. Aliases: `sort` with valig's 'r'/'f' values.

## `sort` (type: `string`):

valig spelling: 'r' = relevance, 'f' = date.

## `experience` (type: `string`):

Required years of experience, e.g. '5'. 'all' or empty means no filter. An integer is accepted too.

## `freshness` (type: `string`):

Only postings newer than this many days. Alias: `jobAge`.

## `jobAge` (type: `string`):

Same as `freshness` — valig spelling.

## `workMode` (type: `array`):

Naukri.com only. Aliases: `wfhType` with valig's '0'/'2'/'3' codes.

## `wfhType` (type: `array`):

valig spelling: '0' office, '2' remote, '3' hybrid.

## `postedBy` (type: `array`):

'1' company jobs, '2' consultant jobs. Naukri.com only. Alias: `jobPostType`.

## `jobPostType` (type: `array`):

Same as `postedBy` — valig spelling.

## `cities` (type: `array`):

Naukri.com city gids (`cityTypeGid`), e.g. '97' Pune, '139' Chennai, '183' Bengaluru. Every record carries the gid of its own locations, so a first run tells you the ids you want.

## `department` (type: `array`):

Naukri.com department gids (`functionAreaIdGid`).

## `industry` (type: `array`):

Naukri.com industry gids (`industryTypeIdGid`).

## `roleCategory` (type: `array`):

Naukri.com role-category gids (`glbl_qcrc`); every record carries its own in `roleCategoryGid`.

## `role` (type: `array`):

Naukri.com role gids (`roleTypeFilterGid`) — a granular child of role category.

## `companyType` (type: `array`):

Naukri.com company-size gids (`qbusinessSize`). On NaukriGulf this maps to the employer cluster instead.

## `salaryRange` (type: `array`):

Naukri.com salary bands (`ctcFilter`), e.g. '3to6', '6to10', '10to15'.

## `topCompanies` (type: `array`):

Naukri.com top-company group ids (`qctopGroupId`).

## `employmentType` (type: `array`):

Naukri.com employment types (`qcemploymentType`).

## `ugCourse` (type: `array`):

Naukri.com undergraduate course gids (`ugTypeGid`).

## `pgCourse` (type: `array`):

Naukri.com postgraduate course gids (`pgTypeGid`).

## `walkin` (type: `boolean`):

Naukri.com only.

## `walkinDate` (type: `string`):

'1' this week, '2' next week, '3' this month. Applies only with walk-in jobs.

## `country` (type: `array`):

NaukriGulf country cluster ids (`ClusterCountry`), e.g. '17' UAE, '14' Saudi Arabia, '13' Qatar.

## `gulfCity` (type: `array`):

NaukriGulf city cluster ids (`ClusterCity`).

## `gulfIndustry` (type: `array`):

NaukriGulf industry cluster ids.

## `gulfFunctionalArea` (type: `array`):

NaukriGulf functional-area cluster ids.

## `gulfSalaryRange` (type: `array`):

NaukriGulf monthly salary cluster ids (`ClusterCTC`).

## `nationality` (type: `array`):

NaukriGulf nationality cluster ids. This filters the *posting's stated preference*, which is public data on the ad; it does not identify candidates.

## `gender` (type: `array`):

NaukriGulf gender cluster on the posting.

## `language` (type: `string`):

NaukriGulf content language.

## `urlParam` (type: `array`):

Passed straight through to the search API. Use it for any filter without a field above; repeating a key means 'both of these'.

## `resultsPerPage` (type: `integer`):

Naukri.com page size. The site itself uses 20; larger pages mean fewer requests.

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

Off by default: Naukri answers Apify's own egress without one. It is the exit IP that Naukri scores, so if a run starts getting blocked, turn on the Apify proxy or let the residential fallback below handle it.

## `residentialFallback` (type: `boolean`):

If Naukri blocks the configured tier, retry once on RESIDENTIAL in-country (IN for Naukri.com, AE for NaukriGulf) instead of failing. A healthy run never pays residential bandwidth.

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

How many requests to run at once.

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

Throttle, in requests per minute across the whole run.

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

How many times to retry a request that fails or is blocked, rotating the session between attempts.

## Actor input object example

```json
{
  "jobBoard": "naukri",
  "keyword": "python developer",
  "maxJobs": 100,
  "outputFormat": "normalized",
  "verifyFilters": true,
  "sortBy": "relevance",
  "experience": "all",
  "freshness": "all",
  "walkin": false,
  "language": "english",
  "resultsPerPage": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "residentialFallback": true,
  "maxConcurrency": 8,
  "maxRequestsPerMinute": 240,
  "maxRequestRetries": 3
}
```

# Actor output Schema

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

All job records. Append ?format=csv for CSV.

## `datasetUrl` (type: `string`):

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 = {
    "keyword": "python developer",
    "maxJobs": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("diopside/naukri-jobs").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",
    "maxJobs": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("diopside/naukri-jobs").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",
  "maxJobs": 100
}' |
apify call diopside/naukri-jobs --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,diopside/naukri-jobs"
        }
    }
}
```

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/p6ZPGadBSyRfw6r0N/builds/GkNLqmMmdC2tU2Krx/openapi.json
