# Apna Jobs Scraper — 50 Categories, 23 Fields, Monitor Mode (`themineworks/apna-jobs-scraper`) Actor

Scrape live job listings from Apna.co, India's largest blue-collar and early-career job app. Title, company, salary, location, tags by city, category and job type. No login, no anti-bot, pay per job. Works in Claude, ChatGPT & any MCP AI agent.

- **URL**: https://apify.com/themineworks/apna-jobs-scraper.md
- **Developed by:** [The Mine Works](https://apify.com/themineworks) (community)
- **Categories:** Jobs, Lead generation, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.90 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## 💼 Apna.co Job Scraper: Blue-Collar & Early-Career Jobs

### Overview

Apna.co is India's largest job app for blue-collar, entry-level and early-career work — huge in tier-2 and tier-3 cities, covering everything from delivery riders and telecallers to junior accountants and field sales roles. This actor turns Apna's public job listings into structured data: title, company, salary range, location, and the tag chips Apna itself shows (Full Time / Part Time / Field Job / experience level / English requirement) — with an option to pull the full job description and structured salary/experience/date fields straight from Apna's own schema.org markup.

No login, no cookies, no anti-bot workaround needed — Apna's job pages are plain server-rendered HTML with no Cloudflare/Akamai challenge, so this actor runs as a lightweight HTTP scraper (no browser, no residential proxy required).

✅ No login required | ✅ No proxy required | ✅ Pay per job returned | ✅ MCP-ready for AI agents

### Important: how "search" works on this actor

Apna.co is primarily a mobile app. Its website has **no free-text keyword search** — `?q=` and `?search=` query parameters are accepted but silently ignored (verified: identical results regardless of the query string). What the site *does* have is a fixed taxonomy of single-dimension browse pages, each with working pagination:

- **One city** (`jobs-in-pune`, `jobs-in-bengaluru_bangalore`, ...)
- **One category/department** (`dep_sales_bd`, `telecaller_bpo`, `dep_it_information_security`, ...)
- **One job type** (`full_time`, `part_time`)
- **One education level** (`10th_pass`, `12th_pass`)
- **One audience/shift flag** (`freshers`, `female`, `night_shift`, `work_from_home`)

Only **one** of these filters is honoured per request — combining two in one URL (e.g. a city and a category together) was tested and the second one is silently ignored by Apna's own site. This actor is built around that reality rather than pretending otherwise:

- `category` is treated as the closest thing to a keyword search and takes top priority as the primary browse filter, followed by `jobType`, `educationLevel`, and the audience/shift flags, then `city`.
- Whichever of your inputs *isn't* used as the primary filter — plus a free-text `keyword` field the site has no equivalent for at all — is applied as a **client-side post-filter** on top of whatever the primary browse page returns (keyword matches job titles; city matches the listing's location text).

That means you can combine, say, a category *and* a city, and get real, narrower results — just sourced from the category feed and filtered down, not from a combined search Apna itself doesn't support.

### Features

- **City, category, job type, education and audience filters** — mapped directly onto Apna's own browse taxonomy (50+ categories, 70+ cities, with common aliases like Bangalore/Bombay/Calcutta/Delhi/Mysore/Allahabad auto-mapped to Apna's slugs).
- **Keyword post-filter** — narrows whatever feed you selected by job title, since Apna's site has no search API to delegate this to.
- **Tag chips preserved** — Full Time / Part Time / Field Job / experience band / English requirement / gender preference, exactly as shown on the listing card.
- **Optional full description mode** — fetches each job's detail page and pulls Apna's own schema.org `JobPosting` data: full description, structured salary (min/max/unit/currency), months of experience, employment type, posted/valid-through dates, industry, occupational category, and full address.
- **Monitor mode** — run on a schedule and get billed only for jobs not seen in a previous run.

### How it works

The actor requests Apna's own server-rendered job-browse pages (`apna.co/jobs`, `apna.co/jobs/jobs-in-<city>`, `apna.co/jobs/dep_<department>-jobs`, etc.) and parses the `<a data-testid="job-card">` elements already present in the initial HTML response — no JavaScript execution needed. It paginates with Apna's own `?page=N` parameter until either your `maxJobs` budget is reached or Apna's own feed runs out (confirmed: the site returns a real empty page, not a block, once a filter is exhausted — usually somewhere between 500 and 1,200 jobs deep).

When `includeFullDescription` is on, each surviving job (after keyword/city post-filtering) gets one extra request to its detail page, where Apna embeds a complete `schema.org/JobPosting` JSON-LD block — the same structured data Google uses for its own job search rich results. That gives clean, typed fields instead of scraping prose.

### 🧾 Input configuration

```json
{
  "category": "telecaller_bpo",
  "city": "Pune",
  "keyword": "outbound",
  "maxJobs": 100,
  "includeFullDescription": true
}
```

### 📤 Output format

```json
{
  "job_id": "357951921",
  "title": "Delivery Boy",
  "company": "Blinkit Private Limited",
  "location": "Viman Nagar, Pune",
  "city_slug": "pune",
  "salary_text": "₹50,000 - ₹1,00,000",
  "tags": ["Field Job", "Part Time", "Full Time", "Any experience", "No English Required"],
  "employment_type": "PART_TIME",
  "salary_min": 50000,
  "salary_max": 100000,
  "salary_unit": "MONTH",
  "salary_currency": "INR",
  "date_posted": "2026-07-24T13:08:58.663Z",
  "valid_through": "2026-08-05",
  "company_logo": "https://apna-organization-logos.gumlet.io/production/479210?w=128",
  "job_url": "https://apna.co/job/pune/delivery-boy-357951921",
  "scraped_at": "2026-07-31T18:05:00.000Z"
}
```

| Field | Description |
| --- | --- |
| 🆔 `job_id` | Apna internal job ID |
| 📌 `title` | Job title |
| 🏢 `company` | Hiring company name |
| 📍 `location` | Raw location text from the listing card |
| 🏙️ `city_slug` | City slug parsed from the job URL |
| 💰 `salary_text` | Raw salary range text shown on the card |
| 🏷️ `tags` | Tag chips (Full Time / Part Time / Field Job / experience / English / gender) |
| 📃 `employment_type` | Structured employment type — only with `includeFullDescription` |
| 💵 `salary_min` / `salary_max` / `salary_unit` / `salary_currency` | Structured salary — only with `includeFullDescription` |
| ⌛ `experience_months` | Months of experience required — only with `includeFullDescription` |
| 🗓️ `date_posted` / `valid_through` | ISO dates — only with `includeFullDescription` |
| 📝 `description` | Full job description — only with `includeFullDescription` |
| 🔗 `job_url` | Canonical apna.co job URL |

**One more row at the end of every run:** a final `_type: "info"` record — informational only, never billed — with a nudge on scheduling and a link to leave a Store review if the data was useful.

### 💼 Common use cases

**Blue-collar labour market research**
Track live delivery, telecalling and field-sales demand across tier-2/tier-3 cities where Apna dominates and Naukri/LinkedIn have thin coverage.

**Gig-economy competitive intelligence**
Watch Blinkit, Zepto, Swiggy and other gig employers' live hiring volume and pay bands by city, refreshed daily with monitor mode.

**Regional wage benchmarking**
Pull salary ranges by category and city to build pay bands for entry-level and blue-collar roles outside the metro-only data most job boards cover.

**Recruitment & staffing feeds**
Feed a niche staffing agency's pipeline with fresh Apna listings for a specific city or category without a human refreshing the app by hand.

### 🚀 Getting started

1. Open the actor and pick a `category` (Apna's own department taxonomy — the closest thing to a keyword search) and/or a `city`.
2. Optionally narrow further with `jobType`, `educationLevel`, or the audience/shift toggles, and add a `keyword` to post-filter titles.
3. Set `maxJobs` and, if you want full descriptions and structured salary data, turn on `includeFullDescription`.
4. Click Start. Download as JSON, CSV, or Excel, or pull the dataset via API or MCP.

### 🔁 Run on a schedule

1. Run once with the input you want repeated, then click **Save as a task** to keep that exact input.
2. In the Apify Console, go to **Schedules** → **Create new**, pick a frequency (hourly/daily/weekly or a cron expression).
3. Add your saved task under **Actors or tasks to run** and save. It then runs unattended, billed the same pay-per-job way as a manual run.

#### Monitor mode — pay only for NEW jobs

Set `monitorMode: true` and the actor remembers every `job_id` it has already delivered. On the next scheduled run with the same input, only genuinely new jobs are pushed and charged — ideal for a daily "what's new in Pune telecalling" feed without re-paying for the whole listing every time.

### FAQ

**Does this actor support free-text keyword search?**
Not against Apna's own API — the site itself doesn't have one (`?q=` is silently ignored on apna.co). The `keyword` field filters job *titles* from whatever city/category feed you selected, client-side, after fetching.

**Why can't I filter by city AND category at the same time on Apna's site?**
Because Apna's own web pages don't support it — only one browse dimension is honoured per URL. This actor works around that by using your most specific filter as the primary fetch and applying the rest as a post-filter, which narrows results without inventing recall the site doesn't have.

**Does it need a proxy?**
No. Apna's job pages showed no anti-bot challenge in testing — plain HTTP requests return full content. A proxy field is available in the input for resilience if that ever changes.

**How current is the data?**
Apna re-renders these pages on every request — the actor pulls exactly what a real visitor's browser would see, with a `scraped_at` timestamp on every record.

**Can I use it in an AI agent?**
Yes. It's exposed as an MCP tool — see below.

### Use in Claude, ChatGPT & any MCP agent

```
https://mcp.apify.com/?tools=themineworks/apna-jobs-scraper
```

Or call it programmatically with the Apify client:

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });

const run = await client.actor('themineworks/apna-jobs-scraper').call({
  category: 'delivery_person',
  city: 'Bangalore',
  maxJobs: 100,
});

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

Questions or need a custom field set? Reach out through the Apify profile.

# Actor input Schema

## `city` (type: `string`):

City to browse jobs in, e.g. 'Pune', 'Bangalore', 'Delhi'. Common aliases (Bangalore/Bombay/Calcutta/Mysore/Allahabad) are mapped automatically to Apna's own city slugs. Leave blank for all-India. Ignored if 'Category' is set (Apna's site supports ONE primary browse filter per request — see README).

## `category` (type: `string`):

Job category or department to browse. This is Apna's own taxonomy — there is no free-text keyword search on the site itself (see README), so this is the closest thing to a 'search'. Takes priority over City as the primary browse filter.

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

Employment type. Used as the primary browse filter if City/Category are blank.

## `educationLevel` (type: `string`):

Minimum education Apna tags the job for.

## `nightShiftOnly` (type: `boolean`):

Browse only jobs tagged as night shift.

## `workFromHomeOnly` (type: `boolean`):

Browse only jobs tagged as work from home.

## `freshersOnly` (type: `boolean`):

Browse only jobs open to freshers (no experience required).

## `femaleOnly` (type: `boolean`):

Browse only jobs tagged as open to / preferring female candidates.

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

Apna's own site has no full-text job search API — this filters the JOB TITLES returned by the City/Category/type browse above (case-insensitive substring match). Leave blank to keep everything from the selected browse filter.

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

Maximum number of jobs to scrape. Apna's own listing pages exhaust after roughly 500-1200 jobs per filter (the site itself stops paginating), whichever comes first. Hard cap 1000.

## `includeFullDescription` (type: `boolean`):

If true, fetches each job's detail page and pulls the full description plus structured salary/experience/employment-type/dates from Apna's own JobPosting schema.org data (one extra request per job — slower, more complete). If false (default), only the fields visible on the listing card are returned (title, company, location, salary range text, tags) — faster and cheaper.

## `monitorMode` (type: `boolean`):

Run on a schedule and deliver ONLY results not seen in a previous run. You are charged per new result, not for the whole feed each time. Ideal for daily monitoring. Requires the same input across runs.

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

Apna.co's job pages showed no anti-bot challenge during testing (plain server-rendered Next.js pages, no Cloudflare/Akamai), so a proxy is NOT required. Left available for resilience — set a country/group here if you see blocking.

## Actor input object example

```json
{
  "city": "Pune",
  "nightShiftOnly": false,
  "workFromHomeOnly": false,
  "freshersOnly": false,
  "femaleOnly": false,
  "keyword": "delivery",
  "maxJobs": 5,
  "includeFullDescription": false,
  "monitorMode": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("themineworks/apna-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("themineworks/apna-jobs-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call themineworks/apna-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=themineworks/apna-jobs-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/f5UTwqGavZFnezVuu/builds/bhYoYieXDaj3DxQrj/openapi.json
