# MyCareersFuture Jobs Scraper \[💰$0.85] Salary & Monitoring (`corvuslab/mycareersfuture-scraper`) Actor

Scrape all ~100,000 jobs on MyCareersFuture.gov.sg, Singapore's national job portal. 76 fields per job: salary range, skills, company UEN, website & industry, views, applicants, lat/lng & district. Filter by region, postal district, direct employer vs agency, flexible work. Alerts on changes.

- **URL**: https://apify.com/corvuslab/mycareersfuture-scraper.md
- **Developed by:** [Corvuslab](https://apify.com/corvuslab) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.85 / 1,000 results

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

### What does MyCareersFuture Singapore Jobs Scraper do?

MyCareersFuture Singapore Jobs Scraper extracts job listings from **[MyCareersFuture.gov.sg](https://www.mycareersfuture.gov.sg/)**, Singapore's official national job portal, as clean structured data. Every job comes back as a **full 73-field record** — the complete description, the salary range, required skills, the employer's UEN, website and industry, view and applicant counts, and the exact address with latitude/longitude, postal district and region — with no extra step and no "details mode" to switch on. Run it with no code and export to JSON, CSV, Excel, the Apify API or an AI agent.

Give it a keyword, paste MyCareersFuture links, or leave the input empty for the **50 newest jobs posted across Singapore**. Raise the limit and a single run covers the **whole site — roughly 100,000 open jobs**.

> New to Apify? Sign up free and use the included monthly platform credit to try this Actor — no credit card needed.

**Why this scraper**

- ⚡ **Fast & low-cost** — one pass per job, so even whole-site runs stay quick and cheap.
- 🧾 **Rich, typed records** — 73 structured fields per job, not raw HTML.
- 🗺️ **Singapore-native filters** — 5 regions, all 28 postal districts, employer type, flexible work, government schemes.
- ♻️ **Cheap to monitor** — incremental mode returns only new, changed and expired jobs, and flags salary increases and decreases.
- 🔔 **Notifications built in** — Telegram, Slack, Discord or any webhook.
- 🤖 **AI- & API-ready** — compact output, MCP-friendly, one-click integrations.

***

### What data can you extract from MyCareersFuture?

Every record carries **73 fields** grouped like this:

| Group | What you get |
|---|---|
| **Job** | Title, job post ID, URL, categories, employment types, position levels, skills, minimum years of experience, number of vacancies, SSOC occupation code, education level and field-of-study codes |
| **Salary** | Minimum and maximum salary, pay period, currency, normalised monthly minimum/maximum, hidden-salary flag |
| **Location** | Full address, postal code, postal district (name + number), region, latitude, longitude, overseas flag and country |
| **Company** | Company name, UEN, website, industry and industry code, size, description, logo, responsive-employer flag — plus the hiring client's name and UEN when a recruitment agency posts on its behalf |
| **Contacts & demand signals** | Emails, phones, URLs and social profiles pulled from the posting (where the employer included them), plus view count, applicant count, applicant-volume label, repost and edit counts |
| **Dates & status** | Posted date, original posted date, expiry date, last update, status |
| **Description** | Full text as plain text, HTML and Markdown — configurable per run |
| **Monitoring** | Change type (NEW / UPDATED / UNCHANGED / EXPIRED), salary change (INCREASE / DECREASE) with the previous salary, repost detection |

***

### Key features

- 🔎 **Search or URL scraping** — search by keyword (several at once, merged and de-duplicated), or paste MyCareersFuture search and job links.
- 🗺️ **Region & postal-district filters** — target Central, East, West, North or North-East Singapore, or any of the 28 postal districts from D01 Marina/Raffles Place to D28 Seletar.
- 🏢 **Direct employers vs recruitment agencies** — keep only jobs posted by the hiring company itself, or only agency postings. Agencies post over 40% of the jobs on the site, many without naming their client — every record flags them (`isRecruitmentAgency`).
- 🕒 **Flexible work, responsive employers & government schemes** — filter by 6 flexible work arrangements (flexi-hours, telecommuting and more), keep only employers the portal marks as responsive, or only jobs under government schemes such as career conversion programmes.
- 🧑‍🎓 **Graduate & entry-level finder** — set a maximum years of experience (0 or 1) to surface roles open to fresh graduates.
- 🎚️ **All the standard filters too** — 43 job categories, 7 employment types, 9 seniority levels, minimum monthly salary, company name, posted-within-days, and newest-first or highest-salary-first sorting.
- 📇 **Contacts & demand signals** — emails, phones, URLs & social profiles from each posting (filter with `requireContact`), plus views and applicant counts on every job.
- ♻️ **Incremental monitoring with alerts** — only NEW, UPDATED and EXPIRED jobs each run, salary moves and reposts flagged, pushed to Telegram, Slack, Discord or a webhook.

***

### 🚀 How to scrape MyCareersFuture

1. Open the Actor and enter **search keywords** (e.g. `data analyst`), pick filters — or paste a MyCareersFuture URL. Or leave everything empty for the newest jobs in Singapore.
2. Set **Max jobs** (0 = no limit — the whole site in one run).
3. (Optional) Turn on **incremental mode** and a **notification** channel, then **Schedule** it.
4. Click **Start** — results stream into the Output tab.
5. Download as **JSON, CSV or Excel**, or pull from the **API**.

#### Quick-start example input

```json
{
  "query": "data analyst",
  "maxResults": 200,
  "regions": ["Central"],
  "postedBy": "direct",
  "minSalary": 5000
}
```

This returns up to 200 data analyst jobs in Central Singapore, posted directly by the hiring company (no agencies) and paying at least 5,000 a month.

***

### Input

Configure it in the visual editor — no code needed — or pass JSON via the API.
35 inputs are available, grouped exactly as they appear in the editor. Within one filter, several values widen the search (OR); different filters combined narrow it (AND).

#### 🔎 Search

| Field | Type | What it does |
|---|---|---|
| `query` | string | Job titles, skills or company names, e.g. `data analyst`, `nurse`, `python`. Separate several searches with commas — results are merged and de-duplicated. |
| `startUrls` | array | Paste MyCareersFuture search-result links (their filters are applied) or individual job links. |
| `maxResults` | integer | Maximum jobs per run (default 50), shared evenly between several keywords. 0 = no limit. |
| `sortBy` | enum | `newest` (best for monitoring) or `salary` (highest salary first, best for salary research). |

#### 🎚️ Filters

| Field | Type | What it does |
|---|---|---|
| `categories` | array | Any of the 43 MyCareersFuture job categories — Information Technology, Banking and Finance, Healthcare / Pharmaceutical, Public / Civil Service, F\&B and more. |
| `employmentTypes` | array | `Permanent`, `Full Time`, `Part Time`, `Contract`, `Temporary`, `Freelance`, `Internship/Attachment`. |
| `positionLevels` | array | 9 levels from `Fresh/entry level` and `Non-executive` up to `Senior Management`. |
| `regions` | array | `Central`, `East`, `West`, `North`, `North-East`. |
| `districts` | array | Postal districts `1`–`28` (D01 Marina/Raffles Place … D28 Seletar). A job in any selected region or district matches. |
| `minSalary` | integer | Only jobs whose monthly salary range reaches at least this amount. |
| `postedBy` | enum | `any`, `direct` (direct employers only) or `recruiter` (recruitment agencies only, whether or not they name the client). |
| `companyName` | string | Only jobs from companies whose name matches this text, e.g. `DBS`. |
| `flexibleWorkArrangements` | array | `Flexi-Hours`, `Telecommuting`, `Employees Choice of Days Off`, `Staggered Time`, `Compressed Work Schedule`, `Creative Scheduling`. |
| `postedWithinDays` | integer | Only jobs posted in the last N days — pairs well with a daily schedule. |
| `maxYearsExperience` | integer | Only jobs asking for at most this many years of experience — 0 or 1 finds graduate and entry-level roles. |
| `responsiveEmployersOnly` | boolean | Only employers MyCareersFuture marks as responsive to applicants. |
| `governmentSchemeOnly` | boolean | Only jobs offered under a government scheme (e.g. Mid-Career Pathways, Career Conversion Programmes). |

#### 🎯 Lead generation

| Field | Type | What it does |
|---|---|---|
| `requireContact` | enum | `off`, `email`, `phone`, `either` or `both` — keep only jobs whose posting includes that contact. Jobs without a match are not charged. |

#### 📄 Output

| Field | Type | What it does |
|---|---|---|
| `descriptionFormat` | enum | `all`, `text`, `html` or `markdown`. |
| `compact` | boolean | Core fields only (title, company, salary, levels, location, dates) — ideal for AI agents and MCP clients. |
| `excludeEmptyFields` | boolean | Drop null/empty fields for cleaner output. |

#### ♻️ Incremental monitoring

| Field | Type | What it does |
|---|---|---|
| `incrementalMode` | boolean | Emit only what changed since the last run — see incremental mode below. |
| `stateKey` | string | Stable name for the tracked search (auto-derived from your settings if blank). |
| `emitUnchanged` / `emitExpired` | boolean | Also emit UNCHANGED jobs / jobs that disappeared since the last run. |

#### 🔔 Notifications

Credentials are secret inputs — encrypted at rest, masked in the UI and never written to the run log.

| Field | Type | What it does |
|---|---|---|
| `telegramToken` + `telegramChatId` | string | Telegram bot token + chat ID. |
| `slackWebhookUrl` / `discordWebhookUrl` | string | Incoming webhook URL. |
| `webhookUrl` + `webhookHeaders` | string / object | POST structured JSON anywhere — n8n, Make, Zapier. |
| `notificationLimit` | integer | How many jobs to include in each message (1–20, default 5). |

#### ⚙️ Advanced

| Field | Type | What it does |
|---|---|---|
| `maxRequestRetries` | integer | How many times to retry a failed page before giving up (default 3). |
| `ignoreUrlFailures` | boolean | Skip pasted URLs that can't be interpreted instead of failing the run (default on). |

#### More example inputs

Graduate roles with flexible hours, newest first:

```json
{
  "maxYearsExperience": 1,
  "positionLevels": ["Fresh/entry level", "Junior Executive"],
  "flexibleWorkArrangements": ["Flexi-Hours", "Telecommuting"],
  "maxResults": 500
}
```

Recruiter lead list — agency postings in IT that carry an email:

```json
{
  "categories": ["Information Technology"],
  "postedBy": "recruiter",
  "requireContact": "email",
  "maxResults": 0
}
```

Daily salary monitor for the whole east side, with Slack alerts:

```json
{
  "regions": ["East", "North-East"],
  "maxResults": 0,
  "incrementalMode": true,
  "emitExpired": true,
  "slackWebhookUrl": "https://hooks.slack.com/services/..."
}
```

***

### Output

Each dataset item is one job. A real record (description and company text trimmed):

```json
{
  "id": "642dc8f6d1a0f8727d2ff2c96fffab7d",
  "jobPostId": "MCF-2026-1693236",
  "title": "Low-Code Engineer",
  "url": "https://www.mycareersfuture.gov.sg/job/information-technology/low-code-engineer-zentact-systems-642dc8f6d1a0f8727d2ff2c96fffab7d",
  "companyName": "ZENTACT SYSTEMS PTE. LTD.",
  "companyUen": "201104634C",
  "isPostedOnBehalf": false,
  "isRecruitmentAgency": false,
  "companyWebsite": "www.zentactsystems.com",
  "companyIndustry": "INFORMATION TECHNOLOGY CONSULTANCY (EXCEPT CYBERSECURITY)",
  "companyIndustryCode": "62021",
  "isResponsiveEmployer": false,
  "salaryMin": 10000.0,
  "salaryMax": 12500.0,
  "salaryType": "Monthly",
  "salaryCurrency": "SGD",
  "employmentTypes": ["Contract"],
  "positionLevels": ["Middle Management"],
  "categories": ["Information Technology"],
  "skills": ["Outsystems", "SQL", "LLMs", "LLMOps", "DevSecOps", "Enterprise Software", "Reactive Programming"],
  "flexibleWorkArrangements": [],
  "governmentSchemes": [],
  "minimumYearsExperience": 8,
  "numberOfVacancies": 2,
  "ssocCode": "25121",
  "location": "3 Temasek Avenue, Centennial Tower, Singapore 039190",
  "postalCode": "039190",
  "district": "Marina, Raffles Place, People's Park, Cecil",
  "districtId": 1,
  "region": "Central",
  "latitude": 1.29350313990002,
  "longitude": 103.860266667472,
  "postedDate": "2026-09-24",
  "expiryDate": "2026-10-24",
  "status": "Open",
  "repostCount": 0,
  "applicantCount": 0,
  "applicantVolumeLabel": "No applicants yet",
  "viewCount": 0,
  "description": "Position : Low-Code Engineer\n\n Bachelor's degree in Computer Science ... Interested applicants- Please send us resume at careers@zentactsystems.com",
  "extractedEmails": ["careers@zentactsystems.com"],
  "extractedPhones": null,
  "source": "mycareersfuture.gov.sg",
  "scrapedAt": "2026-09-24T13:29:03.772728+00:00"
}
```

Descriptions also come as `descriptionHtml` and `descriptionMarkdown`; incremental runs add the monitoring fields below.

#### Data fields

- **Core** — `id`, `jobPostId`, `title`, `url`, `categories`, `employmentTypes`, `positionLevels`, `skills`, `minimumYearsExperience`, `numberOfVacancies`, `status`.
- **Salary** — `salaryMin`, `salaryMax`, `salaryType`, `salaryCurrency`, `salaryMinMonthly`, `salaryMaxMonthly`, `isSalaryHidden`.
- **Occupation & requirements** — `ssocCode`, `occupationId`, `educationLevelCode`, `fieldOfStudyCode`.
- **Location** — `location`, `postalCode`, `district`, `districtId`, `region`, `latitude`, `longitude`, `isOverseas`, `overseasCountry`.
- **Company** — `companyName`, `companyUen`, `companyWebsite`, `companyIndustry`, `companyIndustryCode`, `companySize`, `companyDescription`, `companyLogo`, `isResponsiveEmployer`, `hiringCompanyName`, `hiringCompanyUen`, `isPostedOnBehalf`, `isRecruitmentAgency`.
- **Contacts & signals** — `extractedEmails`, `extractedPhones`, `extractedUrls`, `socialProfiles`, `viewCount`, `applicantCount`, `applicantVolumeLabel`, `repostCount`, `editCount`.
- **Dates** — `postedDate`, `originalPostedDate`, `expiryDate`, `updatedAt`, `scrapedAt`.
- **Description** — `description`, `descriptionHtml`, `descriptionMarkdown`.
- **Monitoring** — `changeType`, `contentHash`, `salaryChange`, `previousSalaryMin`, `previousSalaryMax`, `isRepost`, `repostOfId`, `repostDetectedAt`, `searchKeyword`.

Missing values are `null`; `compact` returns the core fields only and `excludeEmptyFields` drops empties. The Output tab ships three views: **Overview**, **Salaries** and **Companies & contacts**.

***

### ♻️ How to monitor MyCareersFuture with incremental mode

Schedule the Actor and turn on **incremental mode**: each run compares against the last and emits only **NEW / UPDATED / EXPIRED** jobs. Unchanged jobs are skipped — not emitted and not billed.

- 💹 **Salary moves** — an UPDATED job whose pay changed gets `salaryChange` = `INCREASE` or `DECREASE`, with the previous range.
- 🗑️ **Expired jobs** — jobs gone since the last run come back as EXPIRED (with `emitExpired` on).
- 🔁 **Reposts** — a job re-posted under a new ID is flagged `isRepost`, pointing at the original.

The first run sets the baseline; after that you pay only for what changed, so your cost follows how much MyCareersFuture changes, not how much you watch.

#### Setting up scheduled monitoring

1. Configure your search and filters.
2. Turn on **Incremental mode**, and **Include expired records** if you want to know when jobs close.
3. Set **Max jobs** to 0 (or above the number of matching jobs) — EXPIRED is only reported when a run covers the whole search.
4. Run it once — this seeds the baseline.
5. Open the **Schedules** tab and set a recurring run (e.g. hourly or daily), and add a notification channel.

***

### 🔔 How to set up MyCareersFuture alerts

Get pinged when a matching job appears. Fill in only the channels you want:

| Channel | What to configure |
|---|---|
| ✈️ **Telegram** | `telegramToken` (from @BotFather) + `telegramChatId` |
| 💬 **Slack** | `slackWebhookUrl` (Incoming Webhook URL) |
| 🎮 **Discord** | `discordWebhookUrl` (channel webhook URL) |
| 🪝 **Webhook** | `webhookUrl` receives structured JSON — ideal for n8n / Make / Zapier |

Channels fire independently — a broken one can't stop the scrape or the others. With incremental mode on, you only hear about new and changed jobs.

***

### 💡 What can you do with MyCareersFuture data?

#### Singapore salary benchmarking

MyCareersFuture shows a salary range on almost every posting, making it one of Singapore's richest salary sources. Slice by category, seniority, experience and skills, and track how ranges move over time.

#### Recruitment-agency lead generation

Filter to direct employers and you get a clean list of companies hiring right now, with UEN, website and industry. Add `requireContact` to keep only postings with an email or phone.

#### Graduate and entry-level job boards

Set a maximum of 0–1 years' experience and the Fresh/entry level position to feed a graduate job board, a university careers portal or a newsletter.

#### Hiring-signal intelligence for sales teams

A company posting ten engineering roles in D01 is a company with budget. Track new postings, vacancies and applicant counts by company and industry to time outreach for HR tech, office space, training or staffing services.

#### Labour-market and policy research

Use SSOC occupation codes, education levels, government-scheme flags, region and postal district to study demand across Singapore, and latitude/longitude for heat maps. Scheduled runs build a history of job volume and skill demand.

#### Feed AI agents and LLM pipelines

Send compact JSON straight into an LLM context, an MCP tool or a vector store.

***

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

This Actor uses Apify's **pay-per-event** model: a small fee when a run starts, plus a per-job fee. See the Actor's **Pricing** tab for the current numbers — they're rendered live, so this page never goes stale.

Three things keep your bill down:

- **Filters** — you only pay for the jobs that match.
- **`requireContact`** — jobs without the contact you need are dropped and not charged.
- **Incremental mode** — after the first run you pay only for new and changed jobs.

***

### 🔌 Integrations & export

Export to **JSON, CSV, Excel** or an HTML table, or pull from the **REST API** and the **JavaScript / Python** clients. Runs on a **schedule**, connects to **Google Sheets, Slack, Make, Zapier and n8n**, and works as an **MCP tool** for AI agents.

Also covering Singapore and Southeast Asia from the same publisher: **JobStreet & JobsDB Scraper** and **Kalibrr Job Scraper**.

***

### 🔗 Using the API

Run this Actor from your own code. Example with the Apify Python client:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")

run_input = {
    "query": "data analyst",
    "regions": ["Central"],
    "postedBy": "direct",
    "maxResults": 50,
}

run = client.actor("corvuslab/mycareersfuture-scraper").call(run_input=run_input)

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["title"], item["companyName"], item["salaryMin"], item["salaryMax"])
```

It also works with the JavaScript/TypeScript client, the Apify CLI and the REST API.

***

### ❓ FAQ

**Do I need a MyCareersFuture account or Singpass login?** No. The Actor collects publicly listed jobs only — it runs out of the box with no login, cookies or setup.

**How many jobs can I get from MyCareersFuture?** All of them — roughly 100,000 open jobs. Set `maxResults` to 0 for no limit. Rare filter combinations (e.g. government schemes) have to check many jobs to find each match, so those runs take longer.

**How many jobs have an email or phone number?** A minority: in our testing roughly 1 in 7 postings include an email address and fewer than 1 in 10 a phone number, written into the description by the employer. Use `requireContact` to keep only those jobs — the rest are not charged.

**Why is `hiringCompanyName` empty on most jobs?** It is only filled when an agency posts on behalf of a client it names. Many agencies don't name the client, and on direct postings `companyName` is already the employer. `isRecruitmentAgency` flags every agency posting either way.

**Why are `companySize` or `companyWebsite` often null?** Employers fill these in optionally on MyCareersFuture, and many leave them blank. When the site has no value, the field is `null` (or dropped with `excludeEmptyFields`).

**Are salaries monthly? Are they ever hidden?** Almost every MyCareersFuture posting shows a salary range, and in practice they are monthly. `salaryMinMonthly` / `salaryMaxMonthly` normalise any other pay period to monthly, and `isSalaryHidden` marks the rare job where the employer hid the range.

**Why did my monitoring run not report any EXPIRED jobs?** EXPIRED is only reported when a run covers the whole search — `maxResults` 0, or higher than the number of matching jobs. A run cut short by the limit can't tell a closed job from one it simply didn't reach, so it reports none rather than false ones.

**Why are some codes (education level, field of study, SSOC) numbers instead of labels?** They are the official Singapore classification codes MyCareersFuture uses, returned as-is so they join cleanly with government occupation and education datasets.

***

### ⚖️ Is it legal to scrape MyCareersFuture?

This Actor collects only **publicly available** job listings — the same information anyone can see on MyCareersFuture without logging in. It does not access accounts, applications or anything behind a login.

**You are responsible for how you use the data.** Most of each record is business information (job details, company name, UEN, salary range). But the contact fields — `extractedEmails`, `extractedPhones` and sometimes a name in the description — can identify a real person, usually a recruiter or hiring manager. That makes them **personal data**, and using them is regulated:

- **Singapore PDPA** — the Personal Data Protection Act governs collecting, using and disclosing personal data of individuals in Singapore. Only use contact details for a purpose the person would reasonably expect, such as replying about the role they advertised, and give them a way to opt out.
- **Do Not Call Registry** — before sending marketing calls, SMS or WhatsApp messages to a Singapore number, you must check it against the DNC Registry.
- **Spam Control Act** — unsolicited commercial email and SMS sent in bulk must identify the sender, be labelled as advertising and include a working unsubscribe.
- **GDPR and other laws** — if you or the people you contact are in the EU/UK or another jurisdiction with data-protection law, those rules apply as well.

In practice: don't build bulk cold-outreach or spam lists, don't resell personal contact details, store only what you need and delete it when you're done. If you don't need contacts at all, turn on `compact` — compact records leave the contact fields out entirely.

You are also responsible for complying with MyCareersFuture's terms of use. This section is general information, not legal advice — if you plan to use contact data commercially, check with a lawyer familiar with the PDPA.

Not affiliated with, endorsed by or sponsored by MyCareersFuture, Workforce Singapore or the Government of Singapore.

***

**Keywords:** mycareersfuture scraper · mycareersfuture api · mycareersfuture.gov.sg scraper · scrape mycareersfuture jobs · singapore jobs scraper · singapore job listings · singapore salary data · employer UEN · salary range · SSOC occupation codes · graduate jobs singapore · recruitment agency leads · lead generation · job monitoring · export to CSV · export to Excel · no-code scraper · MCP tool for AI agents

# Changelog

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

# Actor input Schema

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

Job titles, skills or company names to search for, e.g. <code>data analyst</code>, <code>nurse</code>, <code>python</code>. Separate several searches with commas — each runs on its own and results are merged and de-duplicated.

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

Paste search-result links (the filters in the link are applied) or individual job links. Job links are always returned, whatever the filters below say.

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

Maximum number of jobs to return across all searches. Set 0 for no limit — all of Singapore is roughly 100,000 open jobs.

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

Newest first is best for monitoring; highest salary first is best for salary research.

## `categories` (type: `array`):

Only jobs in these categories. Pick several to widen the search.

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

Only jobs with these employment types.

## `positionLevels` (type: `array`):

Only jobs at these position levels.

## `regions` (type: `array`):

Only jobs located in these regions of Singapore.

## `districts` (type: `array`):

Only jobs in these postal districts. Combined with Regions, a job in either matches.

## `minSalary` (type: `integer`):

Only jobs whose salary range reaches at least this monthly amount. Salaries are shown on almost every MyCareersFuture posting, so this filter is reliable.

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

Direct employers only, recruitment agencies only, or both. Agencies are recognised whether or not they name their client — many advertise without one.

## `companyName` (type: `string`):

Only jobs from companies whose name matches this text, e.g. <code>DBS</code>.

## `flexibleWorkArrangements` (type: `array`):

Only jobs offering at least one of these arrangements.

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

Only jobs posted in the last N days. Leave empty for any date. Pairs well with a daily schedule.

## `maxYearsExperience` (type: `integer`):

Only jobs asking for at most this many years of experience — set 0 or 1 to find graduate and entry-level roles.

## `responsiveEmployersOnly` (type: `boolean`):

Only jobs from employers MyCareersFuture marks as responsive to applicants.

## `governmentSchemeOnly` (type: `boolean`):

Only jobs offered under a government scheme such as the Mid-Career Pathways Programme or Career Conversion Programmes.

## `requireContact` (type: `string`):

Keep only jobs that include a contact in the posting. Off = keep everything; Email / Phone = require that channel; Either = at least one; Both = email and phone. Jobs without a match are not charged.

## `descriptionFormat` (type: `string`):

Which version(s) of the job description to include.

## `compact` (type: `boolean`):

Emit only the core fields (title, company, salary, levels, location, dates). Ideal for AI agents and MCP clients.

## `excludeEmptyFields` (type: `boolean`):

Remove null, empty-string and empty-array fields from each record.

## `incrementalMode` (type: `boolean`):

Track jobs between runs and tag each with a changeType (NEW / UPDATED / UNCHANGED / EXPIRED). An UPDATED job whose salary moved is tagged salaryChange = INCREASE or DECREASE, with the previous salary.

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

Stable name for the tracked search. Leave empty to derive one automatically from your search settings.

## `emitUnchanged` (type: `boolean`):

Also emit records that have not changed since the previous run.

## `emitExpired` (type: `boolean`):

Also return jobs that were listed on the previous run but are gone now. Only reported when a run covers the whole search (Max jobs 0, or above the number of matching jobs).

## `telegramToken` (type: `string`):

Bot token from @BotFather.

## `telegramChatId` (type: `string`):

Chat or channel ID, e.g. "-100123456789" or "@yourchannel".

## `slackWebhookUrl` (type: `string`):

Slack incoming-webhook URL.

## `discordWebhookUrl` (type: `string`):

Discord incoming-webhook URL.

## `webhookUrl` (type: `string`):

Any HTTPS endpoint. Receives a JSON POST with the matched records — works with n8n, Make and Zapier.

## `webhookHeaders` (type: `object`):

Extra headers for the webhook request, e.g. {"Authorization": "Bearer xyz"}.

## `notificationLimit` (type: `integer`):

How many records to include in each notification message.

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

Not needed — MyCareersFuture is reached directly. Only enable a proxy if your runs are being refused.

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

How many times to retry a failed request before giving up on it.

## `ignoreUrlFailures` (type: `boolean`):

Skip URLs that cannot be interpreted instead of failing the whole run.

## Actor input object example

```json
{
  "query": "data analyst",
  "maxResults": 50,
  "sortBy": "newest",
  "postedBy": "any",
  "responsiveEmployersOnly": false,
  "governmentSchemeOnly": false,
  "requireContact": "off",
  "descriptionFormat": "all",
  "compact": false,
  "excludeEmptyFields": false,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "notificationLimit": 5,
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "maxRequestRetries": 3,
  "ignoreUrlFailures": true
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `salaries` (type: `string`):

No description

## `companies` (type: `string`):

No description

## `allItems` (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": "data analyst"
};

// Run the Actor and wait for it to finish
const run = await client.actor("corvuslab/mycareersfuture-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": "data analyst" }

# Run the Actor and wait for it to finish
run = client.actor("corvuslab/mycareersfuture-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": "data analyst"
}' |
apify call corvuslab/mycareersfuture-scraper --silent --output-dataset

```

## MCP server setup

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