# Foundit Jobs Scraper (`nice_dev/foundit-jobs-scraper`) Actor

Scrape Foundit (ex Monster India) jobs from its 7 country sites — India, Singapore, Malaysia, Indonesia, Hong Kong, Philippines, Gulf: title, company, salary, experience, skills, recruiter name, applicants, apply link. Up to 9 500 jobs per search.

- **URL**: https://apify.com/nice_dev/foundit-jobs-scraper.md
- **Developed by:** [Nice Dev](https://apify.com/nice_dev) (community)
- **Categories:** Jobs
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

### 💼 What is Foundit Jobs Scraper?

**Foundit Jobs Scraper** extracts **job listings from [Foundit](https://www.foundit.in)** (formerly Monster India) on its **7 country sites: India, Singapore, Malaysia, Indonesia, Hong Kong, the Philippines and the Gulf**: **job title, company, salary, experience, location, skills, posting date, applicants, recruiter name** and the **apply link of the employer**, and on request the **full job description, GPS coordinates, views, company card and the recruiter's phone**. It works as a **Foundit API alternative**: run it on a schedule, call it from your code, or plug it into Make, Zapier or n8n.

Type a **keyword** (`python developer`) and a **city** (`Bangalore`), or paste any Foundit search URL, click **Start**, and download the jobs in JSON, CSV or Excel. No Foundit account, nothing to set up. One search returns **up to 9,500 jobs**, and bigger searches are split automatically to go further.

### 📋 What data can you extract from Foundit?

One item per job, 75 fields:

| Category | What you get |
| --- | --- |
| 🏷️ **Job** | title, link, Foundit job id, country site and country — `Solution Engineering Lead` |
| 🏢 **Company** | name (or confidential), logo, Foundit company id, page with all its jobs, Great Place To Work badge — `Sign On Solutions Private Limited` |
| 💰 **Salary** | text as shown, yearly and monthly min and max in the site's currency, in lakhs on foundit.in, hidden or not — `20,00,000-24,00,000 INR` |
| 🎓 **Experience** | years asked (min, max) and as shown — `5-8 Years` |
| 📍 **Location** | city as shown; with details, every location with state, country and GPS coordinates — `Bengaluru` |
| 🧰 **Skills and role** | key skills, job functions, roles, designations, industries — `Python`, `IT` |
| 🗂️ **Job type** | full or part time, permanent, contract, work from home, walk-in drive (venue, dates, contact), jobs for women, nationalities asked |
| 👤 **Recruiter** | company or consultant, name of the recruiter who posted the job, recruiter id; the recruiter's phone as an option |
| 🕒 **Dates and activity** | posting date, last update, closing date, age as shown, applicants, views, urgently hiring, hot job, still open, one-click apply |
| 🔗 **Origin and apply** | posted on Foundit or copied from another site, and the employer's or original site's apply link |
| 📝 **Description** | full job description as text and HTML, company presentation, headquarters and industries |
| 🔎 **Search** | the keyword, location and search URL that found the job |

Every field, with an example, is listed in the **Output** section below.

Fields marked **detail** in that list (full description, every location with GPS, views, company card, full skills list…) are filled when **Extract details** is on. It is off by default: the results list alone already gives title, company, salary, experience, location, skills, applicants, recruiter name, dates and the apply link of copied jobs.

### ✅ Why use Foundit Jobs Scraper?

- 🌏 **The 7 Foundit sites in one run**: India, Singapore, Malaysia, Indonesia, Hong Kong, the Philippines and the Gulf (UAE, Saudi Arabia, Qatar…), each salary in its own currency.
- 📈 **Up to 9,500 jobs per search**, and searches above that are split automatically into smaller parts to go further. No fixed cap per run.
- 👤 **Recruiter name** on the jobs a recruiter posted on Foundit, and **the recruiter's phone** as an option, charged only when a real number is found.
- 🔗 **Paste what you have**: search URLs of any of the 7 sites (with their filters), company job pages, single job URLs or job ids.
- 🎯 **Every Foundit filter, by name**: experience, salary band, freshness, job type, employment type, company or consultant, industry, function, company, quick apply. Type `IT/Computers - Software` or `Infosys Limited`, no id to look up.
- 🧹 **More filters than Foundit itself**: posting date range, keywords to include or exclude, companies to exclude, experience asked, only jobs with a visible salary, only jobs posted on Foundit (or only the copied ones), Great Place To Work companies, urgently hiring, no confidential companies, a cap per company, only jobs with a recruiter phone.
- 🧭 **Where a job really comes from**: Foundit copies many of its jobs from career sites and other job boards; each job says whether it was posted on Foundit or copied, with the original apply link.
- 🔔 **Monitoring built in**: tick **Only new jobs**, schedule the Actor, and each run returns (and charges) only the jobs it has never delivered before.
- 🗂️ **Several searches in one run**: keywords × locations × country sites, with a cap per search, each job returned once.
- 📊 **Market statistics** (option): one sheet per search — total jobs, top hiring companies, cities, salary bands, experience, top skills, work from home share.
- 🔌 API, scheduling, integrations (Make, Zapier, n8n, Google Sheets…) and JSON/CSV/Excel export via the Apify platform.

### 🚀 How to scrape Foundit

1. Create a free Apify account.
2. Open **Foundit Jobs Scraper**, choose the **Country site**, type **Search keywords** (e.g. `python developer`) and a **Location** (e.g. `Bangalore`), and set the Foundit filters you want.
3. Or paste your own Foundit URLs into **Start URLs** (any search results page, with its filters, a company's job page, or single job pages), or job ids into **Job ids**.
4. Set **Max jobs** (100 by default, 0 = no limit) — and **Max jobs per search** when you run several searches — then click **Start**.
5. Download the dataset in JSON, CSV, Excel or via API.

### 💰 How much does it cost to scrape Foundit?

This Actor uses **pay per event** pricing: you pay for the jobs you get, and the exact prices for your Apify plan are shown in the **Pricing** tab. Platform usage (compute, proxy) is included.

- **`result`**: each job saved from the results list.
- **`result-with-details`**: each job saved with its full job page (**Extract details** on, or a job pasted by URL or id) — one price for the job, details included, not on top of `result`.
- **`recruiter-phone`** (option, off by default): each job delivered with a real phone number by **Add the recruiter's phone** (the recruiter's, or one written in the job text), once per job whatever the count of numbers, on top of the job's price; a job without a number is never charged for it.
- **`market-stats`** (option, off by default): each search sheet of **Add market statistics per search**; the sheet of a search that found no job is free.
- A small fee per **run start**.
- Filters Foundit does not offer are applied by the Actor on every job it reads: a job you keep costs its normal price, a job a filter drops costs only a small filter fee (`filter-check`, or `detail-filter-check` when the filter needs the job page) — filtering never costs more than taking everything.

### ⚙️ Input

```json
{
    "query": "python developer",
    "location": "Bangalore",
    "experience": 3,
    "postedWithinDays": 7,
    "maxItems": 200
}
```

Several searches on two country sites, a cap per search, only recent jobs, only the ones not delivered before:

```json
{
    "country": "gulf",
    "countries": ["singapore"],
    "searchQueries": ["accountant", "sales manager"],
    "locations": ["Dubai", "Singapore"],
    "maxItemsPerQuery": 50,
    "postedAfter": "7 days",
    "onlyNew": true,
    "stateKey": "gulf-singapore"
}
```

Or with your own URLs, full job pages and the recruiter's phone:

```json
{
    "startUrls": [
        { "url": "https://www.foundit.in/srp/results?query=python&locations=Bangalore&experienceRanges=2~5" },
        { "url": "https://www.foundit.in/search/infosys-limited-639690-jobs-career" }
    ],
    "extractDetails": true,
    "includeRecruiterPhone": true,
    "maxItems": 100
}
```

| Field | What it does |
| --- | --- |
| `startUrls` | Foundit search URLs of any of the 7 sites (`https://www.foundit.in/srp/results?query=python&locations=Bangalore`, `https://www.foundit.sg/search/engineer-jobs`), company job pages (`https://www.foundit.in/search/infosys-limited-639690-jobs-career`) or single job pages. Keyword, location and every filter of the URL are kept, and the Foundit filters of the form are added (the URL wins when both set the same one). When filled, the search fields are ignored. Max 1,000 URLs. |
| `jobIds` | Foundit job ids (the number at the end of a job URL, `69508887`), read on the **Country site**, like pasting their job pages. |
| `country`, `countries` | The Foundit site to search: `india` (default), `singapore`, `malaysia`, `indonesia`, `hongkong`, `philippines` or `gulf` (UAE, Saudi Arabia, Qatar…); add more sites in `countries` and each search runs on each of them. Salaries come in the site's currency. |
| `query`, `searchQueries` | Keywords as typed in the Foundit search box: job title, skill, designation or company (`python developer`, `data analyst`). Words separated by commas = any of them (`python, java`). Empty = every job of the location and filters; empty with nothing else at all (no location, Foundit filter, other site, start URL or job id) = a short example run (`python` in Bangalore, 20 jobs). |
| `location`, `locations` | City as typed on Foundit, no id needed (`Bangalore`, `Pune`, `Singapore`, `Dubai`). Empty = the whole country site (with a keyword or a Foundit filter; with nothing else at all, the example run: `python` in Bangalore). Every keyword is searched in every location, on every site (max 500 searches per run). |
| `maxItems`, `maxItemsPerQuery` | Max jobs for the whole run (`100` by default, `0` = no limit), and for EACH search so that the first search cannot use up the whole budget (`0` = no per-search cap). |
| `experience` | Your experience in years: Foundit keeps the jobs whose experience range includes it (`3` keeps 2-5 and 3-7 years). |
| `salaryMin`, `salaryMax` | Yearly salary band in the site's currency, in full (`1000000` = ₹10 lakhs on foundit.in). Foundit keeps the jobs whose band overlaps it, including the jobs that hide their salary. |
| `postedWithinDays` | Jobs posted in the last N days, Foundit's own freshness filter (`1`, `7`, `30`, any number up to `365`). |
| `jobTypes` | `workFromHome`, `permanent`, `contract`, `walkin` (walk-in interviews) or `women` (jobs for women). Several = any of them. |
| `employmentTypes` | `fullTime` or `partTime`. |
| `postedBy` | `company` (the employer itself) or `consultant` (recruitment agencies); `any` by default. |
| `sortBy` | `date` (newest first, default) or `relevance`. With a cap, date gives the newest jobs and reads every job once; relevance can skip a few jobs on long searches. |
| `industries`, `functions` | Names exactly as Foundit shows them (`IT/Computers - Software`, `Sales/Business Development`). Several = any of them. Tip: copy them from a first run. |
| `companies` | Only the jobs of these companies, full names as Foundit shows them (`Infosys Limited`). With an empty keyword: every open job of the company. |
| `companyIds` | Only the jobs of these companies, by Foundit company id (`639690`): the `companyId` column of any result. |
| `quickApplyOnly` | Keep only the jobs that can be applied for in one click on Foundit. |
| `extractDetails` | Open each job page: full description (text and HTML), all IT skills, every location with state and GPS coordinates, views, industries, the employer's apply link and the company card (city, country, industries, presentation). Off by default (charged as a job with details). |
| `includeRecruiterPhone` | Add the recruiter's phone and the phone numbers written in the job text (with job details). The recruiter's mobile number is there on about 1 job in 5 posted directly on Foundit, almost never on jobs copied from other sites; the job text holds a number on about 1 job in 16, copied jobs included. Placeholders, example numbers and switchboard numbers repeated across companies are removed. No extra page read. Off by default, charged once per job delivered with a number. |
| `includeMarketStats` | One sheet per search in the **MARKET_STATS** record of the run's key-value store, computed on the jobs read: total jobs on Foundit, top hiring companies, cities, salary bands (min, median, max), experience asked, top skills, work from home share, company or consultant, posted on Foundit or copied, quick apply share. No extra page read. Off by default. |
| `postedAfter`, `postedBefore` | Posting date range: `2026-09-01`, or a period before now (`7 days`, `24 hours`, `2 weeks`, `1 month`). |
| `excludeKeywords`, `includeKeywords` | Drop the jobs whose title contains one of these texts (`trainee`; a text inside a longer word counts too: `intern` also drops "International Sales"); keep only the jobs whose title, company name or skills contain one of them (with **Extract details**, the description too). Case and accents ignored. |
| `excludeCompanies` | Drop the jobs whose company name contains one of these words (`staffing`). |
| `experienceMin`, `experienceMax` | Experience the job asks for, in years: its range must reach the minimum (`5`) and start at or below the maximum (`0` = fresher jobs). Jobs without a range are left out. |
| `onlyWithSalary` | Keep only the jobs that show their salary to candidates. |
| `jobSource` | `native` = posted on Foundit by a recruiter (with the recruiter's name and, sometimes, phone); `reposted` = copied by Foundit from career sites and other job boards (about 9 in 10 on foundit.in, with the original apply link); `any` by default. |
| `greatPlaceToWorkOnly`, `urgentOnly` | Keep only the jobs of companies certified Great Place To Work; keep only the jobs marked urgently hiring. |
| `excludeHiddenCompanies` | Drop the jobs whose employer keeps its name confidential. |
| `maxItemsPerCompany` | At most this many jobs of the same company in the run, the first ones read (`0` = no cap). |
| `requirePhone` | Keep only the jobs with a real phone number: the recruiter's or, with **Extract details**, one written in the job text; needs **Add the recruiter's phone**. With **Extract details** the page of a job without a recruiter number is read to look in its text, and a job dropped there costs the page filter fee. |
| `onlyNew`, `stateKey`, `resetState` | Monitoring: only the jobs never delivered under this memory key (`python-bangalore`); `resetState` forgets the memory. |
| Advanced | `proxyConfiguration` (Apify proxy by default, included in the price; the residential proxy is not available), `maxConcurrency`, `maxRequestsPerMinute`, `minRequestIntervalMs`, `maxRequestRetries`, `debugLog`. |

### 📦 Output

One job found by the search `python` in `Bangalore`, with **Extract details** and **Add the recruiter's phone** on (shortened: empty and long fields cut, recruiter's contact masked):

```json
{
    "id": "69508887",
    "url": "https://www.foundit.in/job/solution-engineering-lead-sign-on-solutions-private-limited-bengaluru-bangalore-69508887",
    "title": "Solution Engineering Lead",
    "site": "www.foundit.in",
    "countryCode": "IN",
    "companyHidden": false,
    "country": "india",
    "companyName": "Sign On Solutions Private Limited",
    "companyId": 92682,
    "companyJobsUrl": "https://www.foundit.in/search/sign-on-solutions-private-limited-92682-jobs-career",
    "companyLogoUrl": "https://media.monsterindia.com/logos/xsignoninx/jdlogo.gif",
    "companyCity": "Hyderabad",
    "companyCountry": "India",
    "companyIndustries": [],
    "isGreatPlaceToWork": false,
    "location": "Bengaluru",
    "locations": [
        {
            "city": "Bengaluru / Bangalore",
            "state": "Karnataka",
            "country": "India",
            "countryCode": "IN",
            "latitude": 12.971599,
            "longitude": 77.594563
        }
    ],
    "state": "Karnataka",
    "latitude": 12.971599,
    "longitude": 77.594563,
    "experienceMin": 5,
    "experienceMax": 8,
    "experienceText": "5-8 Years",
    "salaryMin": 2000000,
    "salaryMax": 2400000,
    "salaryMonthlyMin": 166667,
    "salaryMonthlyMax": 200000,
    "salaryCurrency": "INR",
    "salaryMinLakhs": 20,
    "salaryMaxLakhs": 24,
    "salaryText": "20,00,000-24,00,000 INR",
    "salaryHidden": false,
    "skills": [
        "Ai",
        "implementation experience",
        "Client Interaction",
        "Python",
        "Backend Engineer",
        "Sql",
        "data engineering"
    ],
    "functions": [
        "IT"
    ],
    "roles": [
        "Team Leader/Technical Leader"
    ],
    "designations": [
        "Team Leader/Technical Leader"
    ],
    "industries": [
        "Pharmaceutical"
    ],
    "employmentTypes": [
        "Full time"
    ],
    "jobTypes": [
        "Permanent Job"
    ],
    "isWorkFromHome": false,
    "isWalkIn": false,
    "isForWomen": false,
    "nationalities": [
        "Indian"
    ],
    "postedByType": "consultant",
    "recruiterName": "Suman S.",
    "recruiterId": 282161,
    "recruiterPhone": "94406XXXXX",
    "descriptionPhones": [],
    "applicants": 67,
    "views": 46,
    "isUrgentlyHiring": false,
    "isHotJob": false,
    "hasScreeningQuestions": false,
    "isActive": true,
    "isEarlyApplicant": false,
    "quickApply": true,
    "source": "native",
    "leadScore": 80,
    "leadSignals": [
        "native",
        "phone",
        "fresh",
        "salary",
        "company",
        "active"
    ],
    "jobClassification": "ORGANIC",
    "publishedAt": "2026-10-20T14:55:38.000Z",
    "updatedAt": "2026-10-20T14:55:38.000Z",
    "postedText": "a day ago",
    "closesAt": "2026-12-18T18:30:00.000Z",
    "descriptionHtml": "<p><strong>Solution Engineering Lead </strong></p><p><strong>Role Overview</strong></p><p>We are seeking a Lead Implemen…",
    "description": "Solution Engineering Lead\nRole Overview\nWe are seeking a Lead Implementation Consultant – AI Application Implementation to drive the successful deployment of Mareana's AI-based ent…",
    "searchQuery": "python",
    "searchLocation": "Bangalore",
    "searchUrl": "https://www.foundit.in/srp/results?query=python&locations=Bangalore&sort=2",
    "scrapedAt": "2026-10-21T22:01:32.731Z"
}
```

You can download the dataset in various formats such as JSON, HTML, CSV or Excel.

#### All 75 fields

| Fields | What you get |
| --- | --- |
| `id`, `url`, `title` | **Job**: Foundit job id, public job page, title |
| `site`, `country`, `countryCode` | Foundit site the job was read on (`www.foundit.in`), the site as chosen in the input (`india`), ISO code of the job's country |
| `companyName`, `companyHidden`, `companyId`, `companyLogoUrl` | **Company**: name (null when the employer keeps it confidential, `companyHidden` is then true), Foundit company id (input **Companies (Foundit ids)**), logo |
| `companyJobsUrl`, `companyPageUrl`, `isGreatPlaceToWork` | Foundit page with all the company's jobs, company page on Foundit when there is one, Great Place To Work certified |
| `companyDescription`, `companyCity`, `companyCountry`, `companyIndustries` | company presentation; headquarters city, country and industries (detail) |
| `location`, `locations` | **Location**: as shown on the results list; every location with state, country and GPS (detail; results list: cities only) |
| `state`, `latitude`, `longitude` | state and GPS coordinates of the first location (detail) |
| `experienceMin`, `experienceMax`, `experienceText` | **Experience** asked, in years, and as shown (`5-8 Years`); null when the job states none (the site shows nothing) |
| `salaryMin`, `salaryMax`, `salaryMonthlyMin`, `salaryMonthlyMax`, `salaryCurrency` | **Salary**: yearly and monthly band in the site's currency (`INR`, `SGD`, `AED`…); null when hidden |
| `salaryText`, `salaryHidden` | salary as shown (`42,000-54,000 SGD`, `20,00,000-24,00,000 INR`) and hidden from candidates or not, on all 7 sites |
| `salaryMinLakhs`, `salaryMaxLakhs` | India only: yearly band in lakhs of rupees |
| `skills`, `functions`, `roles`, `designations`, `industries` | **Skills and role**: key skills (detail: the full IT skills list), job functions, roles, designations, industries of the job |
| `employmentTypes`, `jobTypes`, `isWorkFromHome`, `isForWomen`, `nationalities` | **Job type**: full or part time; permanent, contract, work from home, walk-in…; jobs for women; nationalities asked (Gulf and South-East Asia sites) |
| `isWalkIn`, `walkInVenue` | walk-in interview, with the venue, dates and contact of the drive |
| `postedByType`, `recruiterName`, `recruiterId`, `recruiterPhone`, `descriptionPhones` | **Recruiter**: `company` or `consultant`; name of the recruiter who posted the job (null when Foundit only shows the company); Foundit recruiter id; mobile number and phone numbers written in the job text, 5 at most, with job details (option **Add the recruiter's phone**) |
| `applicants`, `views`, `isEarlyApplicant`, `quickApply` | **Activity**: candidates who applied, views (detail), few applicants yet, one-click apply on Foundit |
| `isUrgentlyHiring`, `isHotJob`, `hasScreeningQuestions`, `isActive` | urgently hiring, "hot job" on Foundit, screening questions asked, job still open |
| `source`, `jobClassification` | **Origin**: `native` (posted on Foundit by a recruiter) or `reposted` (copied from a career site or another job board); Foundit's raw classification |
| `leadScore`, `leadSignals` | **Lead score** for a recruitment agency, 0 to 100, free and computed from the row's own fields: is the company hiring actively and can it be reached? Points: `native` 20 (posted on Foundit by the employer), `phone` 20 (a real phone number, the recruiter's or one in the job text, counted even when the option is off), `urgent` 15 (urgently hiring), `fresh` 15 (published 7 days or less before the run), `salary` 10 (salary shown), `company` 10 (company named), `active` 5 (job still open), `fewApplicants` 5 (fewer than 50 applicants). `leadSignals` lists the ones the job has. |
| `applyUrl`, `applyHost` | employer or original site to apply on, and its host (`linkedin.com`) |
| `publishedAt`, `updatedAt`, `closesAt`, `postedText` | **Dates** (ISO 8601): posting, last update, closing date set by the employer; age as shown (`a day ago`) |
| `description`, `descriptionHtml` | **Description** (detail): full job description as plain text and as HTML |
| `searchQuery`, `searchLocation`, `searchUrl`, `scrapedAt` | **Search**: keyword, location and Foundit search URL that found the job (null for job URLs and ids); time of the extraction |

### 💡 Tips

#### How to get more results

One Foundit search gives up to 9,500 jobs. Above that, the Actor splits the search automatically by city, then by years of experience, and reads each part, to go beyond 9,500 jobs (a search such as all jobs in Bangalore counts more than 50,000). Set `maxItems` to `0` for no cap, or use several keywords, locations and country sites.

#### How to reduce costs

The price is per job, so the levers are `maxItems`, `maxItemsPerQuery`, the Foundit filters (free: Foundit only returns the matching jobs), the Actor's own filters (a dropped job costs only the filter fee) and `onlyNew` for recurring runs (you never pay twice for the same job). Leave **Extract details** off when the results-list fields are enough: a job with its full page costs more than a job from the list.

#### Several searches in one run

Fill `searchQueries` and / or `locations` (and `countries`): the Actor runs one search per keyword × location × country site (3 keywords × 4 cities = 12 searches, up to 500 per run). The single `query` and `location` fields still work and are added to the lists. A job found by several searches is saved — and charged — once. Set `maxItemsPerQuery` to give every search its own cap: without it the first searches can use up the whole `maxItems` budget. You can also paste several search URLs into `startUrls`: each one is a search of its own, with the same cap.

#### Monitoring: only the new jobs

Tick **Only new jobs** (`onlyNew`) and schedule the Actor. The first run returns everything; each later run skips the jobs already delivered: they are not saved, not charged and, for jobs found by a search, their page is not even opened. The memory lives in a named key-value store of your account (`foundit-jobs-scraper-seen`, up to 150,000 jobs per key) and is only updated with jobs that really reached the dataset, so a failed run never hides anything. Give each schedule its own `stateKey` (two schedules sharing a key would hide each other's jobs), and tick `resetState` once to start over. Searches are then read newest first, and a search stops once it meets a long run of jobs you already have.

#### Filter by posting date

`postedAfter` and `postedBefore` take a date (`2026-09-01`, the whole day is included, India time) or a period before now (`7 days`, `2 weeks`, `1 month`, `24 hours`; via the API also a full ISO date-time). The filter reads `publishedAt`; a job without a posting date is dropped as soon as a date bound is set. Filtered-out jobs are not saved and do not count in `maxItems` (each job dropped costs the filter fee, see Pricing); the run summary tells how many were filtered. With `postedAfter`, searches are read newest first and stop at the first page that is entirely too old. For the last N days, Foundit's own **Posted within (days)** filter is free.

#### Jobs posted on Foundit or copied

Foundit copies many of its jobs from employers' career sites and other job boards. Set **Job source** to **Posted on Foundit** to keep the jobs a recruiter posted on Foundit itself (recruiter name, sometimes a phone), or to **Copied from other sites** to keep the others, each with its original apply link (`applyUrl`).

### 🔌 Integrations and API

Call the Actor via the Apify API, the JavaScript or Python clients, or connect it with integrations and webhooks (Make, Zapier, n8n, Google Sheets, Slack, Airtable…). The dataset can be fetched as JSON or CSV from any tool.

### 🤖 Use with AI agents (MCP)

AI agents and assistants can find and run this Actor through the [Apify MCP server](https://mcp.apify.com), billed to their Apify account like any run. It returns one item per Foundit job. Actor id: `nice_dev/foundit-jobs-scraper`; MCP server with this Actor only: `https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/foundit-jobs-scraper`.

Smallest input, for a cheap first call:

```json
{
    "query": "python developer",
    "location": "Bangalore",
    "maxItems": 10
}
```

Key output fields: `url`, `title`, `companyName`, `salaryText`, `experienceText`, `location`, `skills`, `publishedAt`, and `description` (with `extractDetails`).

Cost: pay per event — per job saved (`result`, or `result-with-details` with the full job page) plus a small fee per run start, see the pricing section above and the **Pricing** tab. Cap each call with `maxItems` and, through the API, with the run option `maxTotalChargeUsd`.

### ❓ FAQ

#### Is it legal to scrape Foundit?

The Actor only reads what Foundit shows publicly to any anonymous visitor. It logs in to nothing and needs no Foundit account. Results can contain personal data (the name of the recruiter who posted a job and, with the option, the phone number the recruiter published with it and the numbers the employer wrote in the job text), which is protected by laws such as the GDPR, India's Digital Personal Data Protection Act and the data protection laws of Singapore, Malaysia, Indonesia, Hong Kong, the Philippines and the Gulf countries: do not store or use it without a legitimate reason. You are responsible for using the data in compliance with Foundit's Terms of Use and applicable law. This Actor is not affiliated with Foundit (formerly Monster India).

#### Does it give the recruiter's e-mail or phone number?

Foundit hides the companies' e-mails and phone numbers. A job a recruiter posted on Foundit carries the recruiter's name and, on about 1 job in 5, a mobile number the recruiter published: tick **Add the recruiter's phone** to get it (charged only when a real number is delivered). With **Extract details** the same option also lists the phone numbers the employer wrote in the job text, copied jobs included (about 1 job in 16); e-mail addresses are masked by Foundit, so none is returned. Jobs copied from other sites have no recruiter number: they usually come with the employer's apply link instead.

#### Does it need a login or a proxy?

No login. The proxy is included in the price: leave the default setting (the residential proxy is not available). A request the site turns away is retried at once on a new proxy session, up to 10 times on top of the retries (without a proxy, after a pause of 5 seconds, doubled at each retry up to 150 seconds).

#### Is the data safe to open in Excel or to show on a web page?

Titles and descriptions are the employers' own words, copied as they are. A text can begin with `-`, `+`, `=` or `@` (a title, a phone number): Excel and Google Sheets may read such a cell of a CSV file as a formula or as a number. The Actor leaves the text as it is, so that the JSON and the API give the real value: when you open a CSV, import these columns as text. `descriptionHtml` is the employer's HTML, not sanitized: on a web page, escape every field like any text written by a stranger.

#### Known limitations

- Many Foundit jobs hide their salary: `salaryMin` / `salaryMax` are then null and `salaryHidden` is true (Foundit's salary filter still matches them by their hidden band).
- Above 9,500 jobs, a split search may still miss some jobs (a job only in a city absent from the first page, or a part of the search that is itself above 9,500 jobs); the run log says so when it happens.
- Fields marked detail are null or empty when `extractDetails` is off; `recruiterName` is null on jobs copied from other sites.
- `onlyNew` remembers job ids, not their content: a job whose salary changed is not returned again.
- Two runs sharing the same `stateKey` at the same time may both return the same new job.

**A run that reaches its timeout** stops itself about 45 seconds before it: no new page is asked, what it read is saved and, with `onlyNew`, remembered, and the run ends *Succeeded* with "Stopped before the run's timeout". Resurrect it to go on from there, or give the next run a longer timeout (Run options).

**A run the platform stops without warning** (out of memory)

- Resurrect it: it goes on from where it stood at most a minute before the stop. What it had read since is read again, and the jobs already saved are skipped: none is delivered or charged twice, and `maxItems` still counts them.
- With `onlyNew`, the memory is saved after each write (at most once every 2 seconds): resurrect the stopped run and the jobs it had saved meanwhile join the memory; leave it stopped for good, and the next run may return the jobs of its last 2 seconds once more.

#### Something doesn't work?

The last line of the log counts the jobs saved, filtered out and no longer on Foundit (closed while the run was reading them), and the requests that failed after every retry. Those requests and the closed jobs are listed, with the reason, in the `FAILED_REQUESTS` record of the run's key-value store. A run that saved nothing and had failed requests fails, and its last message gives the cause.

If Foundit changes its pages, you are told instead of paying for blank rows. A results page that counts jobs but gives none the Actor can read is an error (listed in `FAILED_REQUESTS`), never a quiet "No jobs found". If the first 20 jobs read all lack their title, posting date, link, source, company name (a confidential company does not count) or — with `extractDetails` — description, the run saves nothing more, stops and fails, and its last message names the missing field: at most those first jobs are charged. A job that `postedAfter` / `postedBefore` drops because it has no date at all counts among those 20. A run of fewer jobs (a scheduled `onlyNew` run that finds a few new ones, a small **Max jobs**) is checked at its end, from 5 jobs: its jobs are already saved, and the run fails with the missing field instead of ending green.

### 🛟 Support

Open an issue in the **Issues** tab with a link to your run: the run log and the `FAILED_REQUESTS` record of the key-value store show exactly which URLs failed and why.

# Actor input Schema

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

Foundit search-result URLs of any of the 7 country sites (`https://www.foundit.in/srp/results?query=python&locations=Bangalore&experienceRanges=2~5`, `https://www.foundit.sg/search/engineer-jobs`, `https://www.foundit.in/search/infosys-limited-639690-jobs-career`: keyword, location and every filter of the URL are kept, pagination is automatic) or single job URLs (`https://www.foundit.in/job/python-developer-infosys-limited-bengaluru-bangalore-69512911`). When this list is not empty, the search fields below are ignored; filters, caps and monitoring still apply. Max 1 000 URLs. Foundit filters set below are added to the URL's own; when both set the same filter, the URL wins.

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

Foundit job ids (the number at the end of a job URL, `69512911`) to extract directly, like pasting their job URLs, read on the site chosen in **Country**. When this list is not empty, the search fields are ignored.

## `country` (type: `string`):

Which Foundit site to search. Salaries are in that site's currency (INR, SGD, MYR, IDR, HKD, PHP, AED…).

## `countries` (type: `array`):

Search several Foundit sites in one run: each search below is run on each site chosen here, added to **Country site**. Jobs found by several searches are saved once.

## `query` (type: `string`):

Job title, skill, designation or company, as typed in the Foundit search box (`python developer`, `sales`, `data analyst`). Several words separated by commas = any of them (`python, java`). Empty = every job of the location and filters; empty with nothing else at all (no location, Foundit filter, other country site, start URL or job id) = a short example run (`python` in Bangalore, 20 jobs).

## `searchQueries` (type: `array`):

Several keywords in one run: one search per keyword (times each location and each country site). Added to **Search keywords**; jobs found by several searches are saved once.

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

City as typed on Foundit, no id needed: `Bangalore`, `Pune`, `Delhi`, `Singapore`, `Dubai`. Several cities separated by commas = any of them. Empty = the whole country site (with a keyword or a Foundit filter; with nothing else at all, the example run: `python` in Bangalore).

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

Several locations in one run: every keyword is searched in every location (3 keywords × 4 locations = 12 searches, max 500). Added to **Location**.

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

Maximum number of jobs to save for the whole run (after deduplication and filters). 0 = no limit. One Foundit search gives up to 9 500 jobs; bigger searches are split automatically by city.

## `maxItemsPerQuery` (type: `integer`):

Cap for EACH search (keyword × location × country site, or search URL), so that the first search cannot use up the whole **Max jobs** budget. 0 = no per-search cap.

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

Your experience in years: Foundit keeps the jobs whose experience range includes it (`3` = jobs open to 3 years: `2-5`, `3-7`, `1-3`). Empty = all. To bound the range itself, use **Experience asked** below.

## `salaryMin` (type: `integer`):

Yearly salary in the currency of the country site, in full (`1000000` = ₹10 lakhs on foundit.in). Foundit keeps the jobs whose salary range overlaps **Salary from** – **Salary to**, including the jobs that hide their salary from candidates. Empty = all.

## `salaryMax` (type: `integer`):

Upper end of the yearly salary band, same currency. Empty = no upper end.

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

Jobs posted in the last N days (Foundit's own freshness filter: `1`, `3`, `7`, `15`, `30` like the website, any other number works too). For an exact date range use **Posted after** / **Posted before** below.

## `jobTypes` (type: `array`):

Several = any of them. Empty = all.

## `employmentTypes` (type: `array`):

Empty = all.

## `postedBy` (type: `string`):

Jobs posted by the hiring company itself, or by recruitment consultants (agencies).

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

Order of the jobs. With a cap (**Max jobs**), `Date` gives the newest jobs. Relevance can skip a few jobs on long searches (the site reorders them while they are read); date reads every job once. **Posted after** and **Only new jobs** always read by date (newest first), whatever is chosen here.

## `industries` (type: `array`):

Industry names exactly as Foundit shows them (`IT/Computers - Software`, `Banking/Accounting/Financial Services`). Several = any of them. Case ignored. Tip: copy them from the `industries` field of a first run.

## `functions` (type: `array`):

Function names exactly as Foundit shows them (`IT`, `Sales/Business Development`, `Finance & Accounts`). Several = any of them. Tip: copy them from the `functions` field of a first run.

## `companies` (type: `array`):

Only the jobs of these companies, full names as Foundit shows them (`Infosys Limited`, `Accenture Solutions Pvt Ltd`). Combine with an empty keyword to get every open job of a company. For a partial name use **Exclude companies** or the keyword field.

## `companyIds` (type: `array`):

Only the jobs of these companies: Foundit company ids (`639690` = Infosys Limited) — the `companyId` field of any result, or the number in a company jobs URL (`/search/infosys-limited-639690-jobs-career`).

## `quickApplyOnly` (type: `boolean`):

Keep only the jobs that can be applied for in one click on Foundit.

## `extractDetails` (type: `boolean`):

Open each job (1 extra request per job): full description (HTML and text), all IT skills, every location with state and GPS coordinates, job views, industries, apply URL of the employer, and the company card (city, country, industries, about). Charged per job whose page is read (event `result-with-details`, see the pricing). Unticked (default) = the fields of the results list only (faster, cheaper): title, company and profile, salary, experience, skills, applicants, recruiter name, dates, apply link…

## `includeRecruiterPhone` (type: `boolean`):

Adds the recruiter's phone and the phone numbers written in the job text (with job details). `recruiterPhone` is the mobile number the recruiter published with the job (no extra request): Foundit shows a real one on about 1 job in 5 posted directly on Foundit, almost never on jobs copied from other sites. `descriptionPhones` lists the numbers the employer wrote in the job text (about 1 job in 16, copied jobs included). Placeholders (`None`, a company switchboard repeated on hundreds of jobs, wrong length) and example numbers are removed. Charged once per job delivered WITH at least one number (event `recruiter-phone`, see the pricing); unticked (default) = never charged.

## `includeMarketStats` (type: `boolean`):

Adds one record, `MARKET_STATS`, to the run's key-value store (Output tab): one sheet per search, computed on the jobs read: total jobs on Foundit, top hiring companies, cities, salary bands (min / median / max), experience asked, top skills, work from home share, company vs consultant, jobs posted on Foundit vs copied from other sites, quick apply share. One sheet per search you typed or pasted (not per part of a split search), no extra request; a search not read because `maxItems` was reached first has no sheet (set `maxItemsPerQuery` to read every search). Charged once per sheet (event `market-stats`, see the pricing); a search with no job gets a sheet of 0 jobs, never charged; unticked (default) = never charged.

## `postedAfter` (type: `string`):

Only jobs posted on or after this date (Foundit's posting date, `publishedAt`): `2026-09-01`, or a period before now such as `7 days`, `24 hours`, `2 weeks`, `1 month` (full ISO date-times work too). A date without a time starts at midnight India time (UTC+5:30), whatever the site.

## `postedBefore` (type: `string`):

Only jobs posted on or before this date (the whole day is included, India time whatever the site), or older than a period such as `30 days`.

## `excludeKeywords` (type: `array`):

Drop the jobs whose title contains one of these texts (case and accents ignored). A text inside a longer word counts too: `intern` also drops "International Sales".

## `includeKeywords` (type: `array`):

Keep only the jobs whose title, company name or skills contain at least one of these words (case and accents ignored). With **Extract details**, the full description is read too. Empty = all.

## `excludeCompanies` (type: `array`):

Drop the jobs whose company name contains one of these words (`Infosys`, `staffing`). Case and accents ignored.

## `experienceMin` (type: `integer`):

Keep only the jobs whose experience range reaches this number of years (`5` keeps `3-7 Years` and `5-10 Years`, drops `0-2 Years`). Jobs without an experience range are left out. A minimum above the maximum is refused.

## `experienceMax` (type: `integer`):

Keep only the jobs whose experience range starts at or below this number of years (`2` keeps `0-1 Years` and `2-5 Years`, drops `3-7 Years`; `0` = fresher jobs). Jobs without an experience range are left out.

## `onlyWithSalary` (type: `boolean`):

Keep only the jobs that show their salary to candidates (few do: under 1 in 10 on foundit.in).

## `jobSource` (type: `string`):

Foundit copies many jobs from employers' career sites and other job boards (about 9 in 10 on foundit.in). `Posted on Foundit` keeps the jobs a recruiter posted on Foundit itself (with recruiter name and, sometimes, phone); `Copied from other sites` keeps the others (with the original apply URL).

## `greatPlaceToWorkOnly` (type: `boolean`):

Keep only the jobs of companies certified Great Place To Work (badge shown by Foundit).

## `urgentOnly` (type: `boolean`):

Keep only the jobs marked "Urgently hiring" by the employer.

## `excludeHiddenCompanies` (type: `boolean`):

Drop the jobs whose employer hides its name.

## `maxItemsPerCompany` (type: `integer`):

Keep at most this many jobs of the same company in the run (the first ones read). 0 = no cap.

## `requirePhone` (type: `boolean`):

Keep only the jobs with a real recruiter phone number. Needs **Add the recruiter's phone** (the run is refused without it).

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

Skip the jobs that a previous run (same **Memory key**) already delivered: they are not saved and not charged and, for jobs found by a search, their page is not even opened. First run = everything is new.

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

Name of the memory used by **Only new jobs**. Give each schedule / task its own key (e.g. `python-bangalore`) so that they do not share their memory. Letters, digits, `-` and `_`.

## `resetState` (type: `boolean`):

Forget everything remembered under this **Memory key** before the run: this run returns (and charges) every job again. Untick it afterwards.

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

Apify Proxy or your own proxies. Keep the default: it is included in the price. The residential Apify proxy is not available in this Actor.

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

Maximum number of requests processed in parallel.

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

Most requests to the site in any 60 seconds, all of them counted: results pages, listing pages and the extra page read for a listing. A budget, not an even pace: up to this many can leave at once when the minute starts (spread them with the minimum delay below). Lower it if the site answers HTTP 429 / 403 in the log.

## `minRequestIntervalMs` (type: `integer`):

Smallest gap between two requests, in milliseconds. Unlike the per-minute rate, this spreads the requests evenly instead of letting them go out in a burst. 0 = no gap.

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

Retries per request before it is marked as failed. Behind a proxy, a request the site turns away is also retried on a new proxy session up to 10 times without using up these retries.

## `debugLog` (type: `boolean`):

Include debug messages in the run log.

## Actor input object example

```json
{
  "startUrls": [],
  "jobIds": [],
  "country": "india",
  "countries": [],
  "query": "python",
  "searchQueries": [],
  "location": "Bangalore",
  "locations": [],
  "maxItems": 100,
  "maxItemsPerQuery": 0,
  "jobTypes": [],
  "employmentTypes": [],
  "postedBy": "any",
  "sortBy": "date",
  "industries": [],
  "functions": [],
  "companies": [],
  "companyIds": [],
  "quickApplyOnly": false,
  "extractDetails": false,
  "includeRecruiterPhone": false,
  "includeMarketStats": false,
  "excludeKeywords": [],
  "includeKeywords": [],
  "excludeCompanies": [],
  "onlyWithSalary": false,
  "jobSource": "any",
  "greatPlaceToWorkOnly": false,
  "urgentOnly": false,
  "excludeHiddenCompanies": false,
  "maxItemsPerCompany": 0,
  "requirePhone": false,
  "onlyNew": false,
  "stateKey": "default",
  "resetState": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxConcurrency": 8,
  "maxRequestsPerMinute": 120,
  "minRequestIntervalMs": 0,
  "maxRequestRetries": 5,
  "debugLog": false
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `marketStats` (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 = {
    "query": "python",
    "location": "Bangalore",
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("nice_dev/foundit-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 = {
    "query": "python",
    "location": "Bangalore",
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("nice_dev/foundit-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 '{
  "query": "python",
  "location": "Bangalore",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call nice_dev/foundit-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/foundit-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/wN75tfDPl4iBHdOhz/builds/4cCR6htc2VzYWh6JR/openapi.json
