# Cutshort Jobs Scraper - India Startup & Tech Jobs (`rjmacarthy/cutshort-jobs-scraper`) Actor

Scrape Cutshort.io jobs: India startup and tech roles with parsed salary (INR) and experience ranges, skills, remote policy, company stage and size. Search by skill and city or paste listing URLs. Only-new mode for alerts. No login, no start fee.

- **URL**: https://apify.com/rjmacarthy/cutshort-jobs-scraper.md
- **Developed by:** [rj](https://apify.com/rjmacarthy) (community)
- **Categories:** Jobs, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

## Cutshort Jobs Scraper - India Startup & Tech Jobs

Scrape public job listings from [Cutshort](https://cutshort.io), India's job board for startup and tech roles. Give it skills or roles (python, reactjs, data engineering) and optionally a city or "remote", or paste any `cutshort.io/jobs/...` listing URL. You get one clean JSON row per job, with the **salary range already parsed into numbers** (INR per year, or per month for internships), the experience range in years, skills, remote policy, posted date and company details (stage, size, type, founded year, website). Unlike the alternatives there is **no start fee**: you pay per job only. An **only-new mode** turns it into a job alert, and it reads only the public listing pages that Cutshort's robots.txt allows. It never touches detail, apply or profile pages, and it doesn't output recruiter names or contact details. The output schema matches our other job scrapers (Dice, SEEK, Reed, Internshala, Workday), so you can merge the feeds.

### What data can you get

| Field | Example |
|---|---|
| `title` | Senior Data Engineer |
| `companyName`, `companyUrl`, `companyLogoUrl`, `companyWebsite` | VY Systems, cutshort.io/company/..., logo, vysystems.com |
| `companyStage`, `companySize`, `companyType`, `companyFoundedYear` | Raised funding, 20-100, Product, 2019 |
| `hiringForClient` | `true` when a recruiter posts for an undisclosed client |
| `locations`, `isRemote`, `workArrangement` | \["Bengaluru (Bangalore)", "Mumbai"], true, remote-or-office |
| `minExperience`, `maxExperience`, `experienceText` | 4, 8, "4 - 8 years" |
| `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod`, `salaryHidden`, `salaryText` | 1300000, 1600000, INR, year, false, "₹13L - ₹16L / yr" |
| `skills`, `jobTypes` | \["Python", "Django", "AWS"], \["full-time"] |
| `postedAt` | 2026-11-04T11:28:16.592Z |
| `description`, `descriptionHtml` | Full job description (plain text and HTML) |
| `id`, `url`, `searchSlug`, `searchUrl`, `scrapedAt` | Stable job id, public job URL, where it was found |

### Use cases

- **Job alerts**: schedule a daily run with `onlyNew` and get only jobs you haven't seen, in Slack, email or a Google Sheet.
- **Salary benchmarking**: compare INR salary ranges by skill, city, experience band and company stage.
- **Startup hiring signals**: see which funded or profitable startups hire for which skills, for sales prospecting or investor research.
- **Job aggregators and boards**: feed Indian tech jobs into your own site, in the same schema as our other job scrapers.
- **Talent market research**: track demand for skills (GenAI, Kubernetes, Golang) across Bangalore, Pune, Hyderabad and remote.

### How to use

1. Enter one or more **keywords** (skills or roles). Each keyword becomes one Cutshort listing page.
2. Optionally pick a **city** or **Remote**.
3. Set **Max jobs** and run. Results appear in the dataset; export them as JSON, CSV or Excel, or read them through the API.

Python jobs in Bangalore:

```json
{
    "keywords": ["python"],
    "location": "bangalore",
    "maxItems": 100
}
```

Several remote roles, only new ones since the last run (for a daily schedule):

```json
{
    "keywords": ["reactjs", "nodejs", "golang"],
    "location": "remote",
    "maxItems": 200,
    "onlyNew": true,
    "stateKey": "remote-dev-alert"
}
```

Any listing page or slug, e.g. collections like funded startups:

```json
{
    "startUrls": [{ "url": "https://cutshort.io/jobs/fullstack-developer-jobs-in-pune" }],
    "searchSlugs": ["funded-startup-jobs", "product-based-company-jobs"],
    "maxItems": 100
}
```

**Keywords.** They map to Cutshort's listing slugs (`/jobs/{keyword}-jobs`). Common spellings are translated for you: React → `reactjs`, Node → `nodejs`, ML / machine learning → `machine-learning-ml`, AI → `artificial-intelligence-ai`, data science → `datascience`, full stack → `fullstack-developer`. If a keyword has no listing page, the run logs a warning for that keyword and carries on. To find the exact slug, open [cutshort.io/jobs](https://cutshort.io/jobs), click a category and copy the URL into **Start URLs**.

**Cities.** Cutshort has city pages for Ahmedabad, Bangalore, Bhubaneswar, Chandigarh, Chennai, Coimbatore, Delhi NCR (Gurgaon, Noida), Hyderabad, Indore, Jaipur, Kochi, Kolkata, Mumbai and Pune. With a city and no keyword, you get all startup jobs in that city.

### Output example

A real item (description shortened):

```json
{
    "id": "6aeb16d009eeef45c0a1ff49",
    "url": "https://cutshort.io/job/python-with-GenAi-Bengaluru-Bangalore-Hyderabad-VY-SYSTE",
    "title": "python with GenAi",
    "companyName": "VY SYSTEMS PRIVATE LIMITED",
    "companyId": "676cda781975060026864b32",
    "companyUrl": "https://cutshort.io/company/vy-systems-private-limited-16-e43Khktp",
    "companyLogoUrl": "https://cdnv2.cutshort.io/company-static/676cda781975060026864b32/user_uploaded_data/logos/company_logo.png",
    "companyWebsite": "https://vysystems.com",
    "companyType": "Services",
    "companySize": "100-1000",
    "companyStage": "Profitable",
    "companyFoundedYear": 2000,
    "companyDescription": "Vy Systems is a Global Technology consulting, Solutions, and Managed Technology Services company. We service our customers...",
    "hiringForClient": false,
    "locations": ["Bengaluru (Bangalore)", "Hyderabad"],
    "locationsText": "Bengaluru (Bangalore), Hyderabad",
    "isRemote": false,
    "workArrangement": "office",
    "minExperience": 6,
    "maxExperience": 12,
    "experienceText": "6 - 12 years",
    "salaryMin": 500000,
    "salaryMax": 2600000,
    "salaryCurrency": "INR",
    "salaryPeriod": "year",
    "salaryHidden": false,
    "salaryText": "₹5L - ₹26L / yr",
    "skills": ["Python", "Generative AI (GenAI)", "RAG", "LangGraph"],
    "jobTypes": ["full-time"],
    "postedAt": "2026-11-04T11:28:16.592Z",
    "description": "Job Summary\nWe are looking for an experienced Python Developer with strong expertise in Generative AI (GenAI), Large Language Models (LLMs)...",
    "descriptionHtml": "<p>Job Summary</p><p>We are looking for an experienced Python Developer...</p>",
    "searchSlug": "python-jobs-in-bangalore-bengaluru",
    "searchUrl": "https://cutshort.io/jobs/python-jobs-in-bangalore-bengaluru",
    "scrapedAt": "2026-11-04T12:28:45.409Z"
}
```

The dataset has three views: **Overview**, **Salary & experience** and **Companies**. A `RUN_SUMMARY` record in the key-value store lists every search with its status, pages, job counts and the number of jobs Cutshort reports for that listing.

### Pricing

Pay per event, no start fee:

| Event | Price |
|---|---|
| `job`: one job listing in the dataset | $0.0015 |

Worked example: **1,000 jobs ≈ $1.50**. The prefill (10 Python jobs) costs about $0.015. Platform usage is small: one request returns 50 jobs. Set **Maximum cost per run** in the run options and the Actor stops cleanly when it reaches it. In only-new mode you pay only for jobs that are new.

### Tips and limits

- **Max jobs counts across all searches.** Searches run one after another, so with 3 keywords and `maxItems: 100` the first keyword can use the whole budget. Raise the limit, or run one keyword per task.
- **Volume per listing.** Each listing page returns 50 jobs per page, and the Actor pages through all of them (a broad listing like `python-jobs` has 4,000+). Cutshort lists newest first. If new jobs are posted mid-run, pages can shift slightly; duplicates are removed by job id.
- **Salary numbers are the displayed range.** Cutshort shows employers' "displayed" range; we output those numbers so they match `salaryText`. When the employer hides the salary ("Best in industry"), `salaryMin`/`salaryMax` are null and `salaryHidden` is true. For "Upto ₹30L" only `salaryMax` is set. Internship stipends have `salaryPeriod: "month"`.
- **No equity field.** Cutshort's listing data has no structured equity/ESOP field, so we don't invent one; mentions in the description text stay in `description`.
- **Agency listings.** When a recruiter posts for an undisclosed client (`hiringForClient: true`), `companyName` is the client blurb and there's no company page. Company stage and size are missing for about a third of jobs because the company didn't fill them in.
- **Only-new mode** remembers job ids per `stateKey` for 90 days. The first run outputs everything and becomes the baseline, so give it a large `maxItems` (or 0) to cover the whole listing. Later runs stop paging at the first page with no new jobs (Cutshort lists newest first), so a daily alert usually costs 1-2 requests per keyword.

### FAQ

**Is it legal to scrape Cutshort?**
The Actor reads only public job listings that anyone can see without logging in, and only pages that Cutshort's robots.txt allows: listing pages and their page-2, page-3 data, never `/view/j/`, `/vj/`, `/profile/`, `/apply/` or the disallowed query strings. It doesn't output recruiter names, photos, emails or phone numbers (contact details found inside a description are replaced with `[redacted]`). You are responsible for using the data in line with Cutshort's terms, the DPDP Act, GDPR and other laws that apply to you.

**Do I need a Cutshort account or cookies?**
No.

**Do I need a proxy?**
Usually not. If Cutshort starts answering with HTTP 403/429, enable Apify Proxy (datacenter). Residential proxies are not supported: if you pick the RESIDENTIAL group, the Actor logs a warning and uses Apify datacenter proxy instead.

**My keyword returned nothing.**
The log and `RUN_SUMMARY` say "Cutshort has no listing page /jobs/...". Open [cutshort.io/jobs](https://cutshort.io/jobs), find the category and paste its URL into Start URLs, or put the slug into **Listing slugs**.

**Can I get the recruiter's email?**
No. Some alternatives sell recruiter contact emails; we deliberately don't collect personal contact data.

**How fresh is the data?**
Live: every run reads Cutshort at that moment.

### Integrations

- **API**: start runs and download the dataset with the [Apify API](https://docs.apify.com/api/v2) or the JavaScript/Python clients.
- **Make, Zapier, n8n**: use the Apify app/node to run the Actor on a schedule and send new jobs to Google Sheets, Slack, Airtable or a CRM.
- **MCP**: AI agents can call this Actor through the [Apify MCP server](https://mcp.apify.com).
- **Webhooks**: get notified when a run finishes.

### Changelog

- **0.1** (2026-11): first release. Keyword + city/remote search, start URLs and slugs, full pagination, parsed salary and experience, company details, only-new mode.

### More scrapers by the same developer

- [ATS Jobs Scraper: Greenhouse, Lever, Ashby & Workday](https://apify.com/rjmacarthy/ats-jobs-scraper)
- [Dice Jobs Scraper](https://apify.com/rjmacarthy/dice-jobs-scraper)
- [Reed.co.uk Jobs Scraper - UK Job Listings with Salary](https://apify.com/rjmacarthy/reed-jobs-scraper)
- [SEEK Jobs Scraper](https://apify.com/rjmacarthy/seek-jobs-scraper)
- [Workday Jobs Scraper](https://apify.com/rjmacarthy/workday-jobs-scraper)
- [AI Visibility Tracker: ChatGPT, Perplexity, Gemini, Claude](https://apify.com/rjmacarthy/ai-search-visibility-tracker)

Browse all my Actors on [my Apify Store profile](https://apify.com/rjmacarthy).

### Support

Found a bug or need a field? Open an issue on the Issues tab with your input and the run link, and we usually reply within a day.

# Actor input Schema

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

Skills or roles, one per line: python, java, reactjs, data engineering, machine learning, fullstack developer, product manager. Each keyword is one Cutshort listing page (/jobs/{keyword}-jobs). Common spellings are mapped for you (React -> reactjs, Node -> nodejs, ML -> machine-learning-ml). An unknown keyword is reported as a warning. Leave empty when you use slugs or start URLs.

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

Narrow every keyword to one city, or to remote jobs. Leave empty for all of India. With no keyword, a city lists all startup jobs in that city.

## `searchSlugs` (type: `array`):

Exact Cutshort listing slugs, i.e. the part after cutshort.io/jobs/: python-jobs-in-pune, funded-startup-jobs, product-based-company-jobs, remote-golang-jobs.

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

Any Cutshort job listing page, e.g. https://cutshort.io/jobs/python-jobs-in-bangalore-bengaluru. Query strings are dropped. Job detail and profile pages are not supported (robots.txt disallows them).

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

Stop after this many jobs in total, across all searches. 0 = no limit (a broad keyword like python has 4,000+ jobs).

## `onlyNew` (type: `boolean`):

Skip jobs already output by earlier runs with the same state key. Use it for scheduled alerts: the first run outputs everything and becomes the baseline. Run the first (baseline) run with a large Max jobs or 0, so the baseline covers the whole listing. Later runs stop at the first page with no new jobs.

## `stateKey` (type: `string`):

Name of the seen-jobs memory, so several schedules can track separate feeds.

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

Not needed normally. Enable Apify Proxy (datacenter) if Cutshort blocks requests. Residential proxies are not supported: a RESIDENTIAL group falls back to Apify datacenter proxy with a warning.

## Actor input object example

```json
{
  "keywords": [
    "python"
  ],
  "maxItems": 10,
  "onlyNew": false,
  "stateKey": "default",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

One item per job: title, company, locations, salary, experience, skills, posted date and URL.

## `jobsFull` (type: `string`):

Every field, including full descriptions and company details.

## `summary` (type: `string`):

Per-search status, counts and request statistics.

# 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"
    ],
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("rjmacarthy/cutshort-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"],
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("rjmacarthy/cutshort-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"
  ],
  "maxItems": 10
}' |
apify call rjmacarthy/cutshort-jobs-scraper --silent --output-dataset

```

## MCP server setup

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