MyCareersFuture Scraper: Singapore Jobs, Salaries, UEN avatar

MyCareersFuture Scraper: Singapore Jobs, Salaries, UEN

Pricing

Pay per event

Go to Apify Store
MyCareersFuture Scraper: Singapore Jobs, Salaries, UEN

MyCareersFuture Scraper: Singapore Jobs, Salaries, UEN

Pull Singapore job listings from MyCareersFuture with salary, skills, company and UEN. Search, scrape URLs, or watch for new posts.

Pricing

Pay per event

Rating

0.0

(0)

Developer

Arkis

Arkis

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Security

Limited permissions

Share

MyCareersFuture Jobs + Monitor

This Actor pulls job listings from MyCareersFuture, Singapore's government jobs board. Every result is a full job record: title, company, UEN, SGD salary range, skills, the full description text, closing date, industry (SSIC) code, vacancies, years of experience, education level, region and map coordinates. You can search by keyword, scrape a list of job URLs, or run it on a schedule to return only new listings since the last run. It works over plain HTTP, so runs are fast and cheap. Pricing is $0.002 per job returned, plus the small platform Actor start fee.

Two optional add-ons are off by default: job change alerts for monitor runs, and company profiles for the employers in your results. Each costs $0.002 per item it produces. If you leave them off, nothing changes.

Use cases

1. Recruiter and BD hiring signals

Recruiters can see who's hiring for a role this week. BD teams can match new openings to their CRM by UEN.

A company that posts many jobs, or suddenly starts hiring for a new function, is a good sales or recruiting lead. Run a scheduled monitor for a category (for example Information Technology with positionLevels: ["Manager", "Middle Management"]) or for one competitor's UEN. Send the new jobs to your CRM or Slack through an Apify integration. The companyUen, ssicCode/ssicDescription (industry), companyWebsite, vacancies, views and numberOfApplications fields help you rank leads.

2. Salary research and talent mapping

Pull every posting for a role family (search: "data engineer", maxItems: 5000). Then compare salaryMin/salaryMax by positionLevel, employmentType, educationLevel, minimumYearsExperience, region and skills. MyCareersFuture requires employers to state a salary range, which makes it a useful public source of Singapore pay data.

3. Job alerts

Job seekers and career coaches can schedule mode: "monitor" hourly or daily with their own filters. Each run outputs only postings that are newer than the previous run. Connect the dataset to email, Telegram or a webhook and you have your own job alert.

Input examples

Search with filters

{
"mode": "search",
"search": "product designer",
"categories": ["Design"],
"employmentTypes": ["Full Time", "Permanent"],
"minSalary": 5000,
"maxSalary": 12000,
"maxItems": 300
}

One employer's jobs

{ "mode": "search", "postedCompanyUen": "200310022N", "maxItems": 1000 }

Specific job URLs, with the raw description HTML

{
"mode": "urls",
"startUrls": [
{ "url": "https://www.mycareersfuture.gov.sg/job/information-technology/java-full-stack-developer-digiworld-technologies-ed8e29d03d2ebf3280cc359c745bc20a" }
],
"includeDescription": true
}

You only need includeDescription if you want the descriptionHtml field. Every result already has descriptionText without it.

Monitor (schedule this)

{
"mode": "monitor",
"search": "software engineer",
"positionLevels": ["Senior Executive", "Manager"],
"postedAfter": "2026-11-01",
"maxItems": 500
}

Monitor with job change alerts and company profiles (both paid add-ons)

{
"mode": "monitor",
"postedCompanyUen": "200310022N",
"maxItems": 500,
"emitJobChanges": true,
"enrichCompanyProfiles": true
}

Input reference

FieldTypeNotes
modesearch | urls | monitorDefault search.
searchstringFree-text keywords. Leave empty to get all jobs, newest first.
categories, employmentTypes, positionLevelsstring[]Exact MyCareersFuture labels, e.g. "Information Technology", "Full Time", "Professional".
minSalary / maxSalaryinteger (SGD/month)minSalary is sent to the API. maxSalary is applied by the Actor after fetching.
postedCompanyUenstringEmployer UEN.
startUrlsURL listFor urls mode. The 32-hex job id at the end of each URL is used.
maxItemsintegerDefault 500. With emitJobChanges, counts new jobs and change items together. Company profiles don't count.
postedAfterISO dateKeeps only jobs posted on or after this date (day precision, Singapore time).
includeDescriptionbooleanDefault false. Only adds the raw descriptionHtml field. Every job already gets a detail fetch, so you get the description text, closing date, SSIC code and everything else either way.
emitJobChangesbooleanDefault false. Paid add-on, monitor mode only. Also outputs previously seen jobs that changed. See below.
enrichCompanyProfilesbooleanDefault false. Paid add-on, any mode. Saves one company profile per unique UEN to the companies dataset. See below.
proxyproxy configurationOptional. The API normally works without a proxy.

How the monitor works

The query parameters (keywords, filters, salary bounds, UEN) are hashed into a key in the named key-value store mycareersfuture-monitor. Changing any filter starts a separate history. The key holds:

  • the job IDs seen in earlier runs (up to the 20,000 most recent),
  • a watermark: the newest postedAt date covered so far,
  • lastRunAt: when the monitor last ran.

The monitor only outputs jobs that are newer than the previous run. It never returns older backlog.

  • First run (no saved state): outputs up to maxItems of the newest matching jobs and sets the watermark to the newest posting date. If maxItems cuts off partway through that day, the Actor keeps reading the rest of that day's listings without outputting them. Those jobs are recorded as seen so the next run doesn't return them as "new". It reads at most 50 pages this way, and these list calls aren't charged.
  • Later runs: output only jobs that are not in the seen set and were posted on or after the watermark date. Results come newest first, so paging stops at the first page where every job is already seen or older than the watermark. Older jobs that were never seen, for example because they fell outside the first run's maxItems, are not output.
  • Limits: if maxItems or your spending limit stops a later run before all new jobs are output, the remaining new jobs are not marked as seen. The watermark also isn't moved past them, so the next run delivers them.

postedAfter still applies as an extra lower bound. Posting dates are day precision (Singapore time), so a job posted later on the watermark day still counts as new.

Optional add-ons

Both are off by default. You only pay for them when you turn them on, and only for the items they actually produce.

Job change alerts (emitJobChanges, $0.002 per changed job)

Search results are sorted by posting date, so a job that gets a pay rise, closes early or is reposted usually doesn't show up near the top again. With emitJobChanges: true in monitor mode, the Actor:

  1. Runs the normal new-job catch-up first (charged as job, same as before).
  2. Re-fetches the most recently seen jobs for this query by ID. It checks up to min(1000, maxItems) of them, newest first, and logs the exact number. Jobs that return 404 are skipped.
  3. Compares each one with the snapshot saved last time. The tracked fields are salaryMin, salaryMax, salaryType, status, closingDate, repostCount, numberOfApplications, vacancies, editCount and title.
  4. Outputs a changed job to the default dataset with itemType: "job-change", a changes list, the previous snapshot in before, and all the normal job fields. It charges one job-change event for each item.

Things to know:

  • Snapshots are stored in the same monitor key-value record as the seen IDs, capped at the same 20,000 jobs.
  • The first run with the toggle on has no change charges. No snapshots exist yet, so it only records them. Jobs seen before you turned the toggle on get a free baseline snapshot the first time they're re-checked.
  • views is stored but never triggers a change by itself. It moves on almost every run. numberOfApplications does trigger one, so busy postings can show up as changed on most runs. Keep that in mind on hourly schedules.
  • Limits: maxItems and your spending limit cover new jobs and change items together. If a limit stops the run before a change is output, that job keeps its old snapshot, so the change is reported on the next run.
  • New jobs get itemType: "job" when this toggle is on. Every other field is the same as before.
  • The toggle is ignored in search and urls mode.

Example change item (job fields shortened):

{
"itemType": "job-change",
"changes": [
{ "field": "salaryMax", "before": 6000, "after": 7000 },
{ "field": "closingDate", "before": "2026-11-19", "after": "2026-12-03" }
],
"before": { "title": "Java Full-Stack Developer", "salaryMin": 3000, "salaryMax": 6000, "status": "Open", "closingDate": "2026-11-19", "numberOfApplications": 12, "views": 140 },
"id": "ed8e29d03d2ebf3280cc359c745bc20a",
"title": "Java Full-Stack Developer",
"salaryMax": 7000,
"closingDate": "2026-12-03",
"...": "all other job fields"
}

Company profiles (enrichCompanyProfiles, $0.002 per unique company per run)

After the jobs are processed, the Actor takes the unique employer UENs from the jobs it output this run. It uses the hiring company's UEN, or the posting company's UEN if there isn't one. It fetches each company's MyCareersFuture profile once and saves it to a separate named dataset called companies, so your job dataset keeps the same shape.

Each record has itemType: "company-profile", uen, name, descriptionText, descriptionHtml, website, employeeCount, ssicCode/ssicDescription (SSIC 2020 when available), logoUrl, registeredAddress (formatted from the address with purpose registered), the raw addresses list, lastSyncDate, jobsInRun (how many of this run's output jobs came from that company), source and scrapedAt.

  • Charged once per UEN per run, not once per job. A 404 or failed lookup isn't charged.
  • It respects your spending limit and logs how many companies were enriched.
  • The data is company-level only, taken from the public MCF profile. No contact details or personal data are collected.
  • The companies dataset is a named dataset, so it stays in your account and collects records across runs. Find it under Storage → Datasets in Apify Console, or call GET /v2/datasets/{your-username}~companies/items. Each record has a scrapedAt timestamp, so you can deduplicate by uen.

Output

Each dataset item is one full job record. Search, monitor and URL modes all fetch every job's detail page, so you get the full set of fields by default. Sample:

{
"id": "ed8e29d03d2ebf3280cc359c745bc20a",
"jobPostId": "MCF-2026-1967545",
"url": "https://www.mycareersfuture.gov.sg/job/information-technology/java-full-stack-developer-digiworld-technologies-ed8e29d03d2ebf3280cc359c745bc20a",
"title": "Java Full-Stack Developer",
"companyName": "DIGIWORLD TECHNOLOGIES PTE. LTD.",
"companyUen": "202003576E",
"postedCompanyName": "DIGIWORLD TECHNOLOGIES PTE. LTD.",
"companyWebsite": "www.digiworld.sg",
"companyLogoUrl": "https://static.mycareersfuture.gov.sg/images/company/logos/baa07d84dc07725220e9c1495111df86/DIGIWORLD%20TECHNOLOGIES%20PTE.%20LTD..jpg",
"companyEmployeeCount": null,
"ssocCode": "21522",
"occupationId": "OCC014584",
"ssicCode": "62011",
"ssicDescription": "DEVELOPMENT OF SOFTWARE AND APPLICATIONS (EXCEPT GAMES AND CYBERSECURITY)",
"salaryMin": 3000,
"salaryMax": 6000,
"salaryCurrency": "SGD",
"salaryType": "Monthly",
"isHideSalary": false,
"employmentType": "Contract",
"positionLevel": "Professional",
"categories": ["Information Technology"],
"skills": ["JSP", "REST APIs development", "Java Applications", "Hibernate Framework", "JPA", "Backend Development"],
"keySkills": [],
"minimumYearsExperience": 4,
"educationLevel": "Bachelor's degree or equivalent",
"flexibleWorkArrangements": [],
"workingHours": null,
"shiftPattern": null,
"address": "10 UBI CRESCENT, UBI TECHPARK, Singapore 408564",
"districts": ["D14 Geylang, Eunos"],
"region": "Central",
"lat": 1.32627524038924,
"lng": 103.896130679533,
"vacancies": 4,
"postedAt": "2026-11-05",
"originalPostedAt": "2026-11-05",
"updatedAt": "2026-11-05T07:11:06.000Z",
"closingDate": "2026-11-19",
"numberOfApplications": 0,
"views": 1,
"repostCount": 0,
"editCount": 0,
"isPostedOnBehalf": false,
"status": "Open",
"descriptionText": "We are looking for a Java Full-Stack Developer with 4–6 years of experience in developing web-based applications ...",
"source": "mycareersfuture",
"scrapedAt": "2026-11-05T07:34:25.571Z"
}

descriptionHtml (the raw HTML of the description) is added only when includeDescription is true. All other fields come back by default. When a job is posted on behalf of another employer, companyName/companyUen refer to the hiring company and postedCompanyName is the agency.

Pricing (pay per event)

EventPrice
Actor start (apify-actor-start, charged by the Apify platform)about $0.01 per GB of memory
job: charged per job scraped and saved to the dataset$0.002
job-change: optional, per changed job output (emitJobChanges, monitor only)$0.002
company-profile: optional, per unique company UEN enriched per run (enrichCompanyProfiles)$0.002

1,000 jobs cost about $2, plus the start fee. The detail fetch for each job is included in the per-job price. The Actor respects your maximum spend per run and stops cleanly when the limit is reached. A monitor run that finds no new jobs costs only the start fee. If you leave both add-ons off, you are never charged for job-change or company-profile. With emitJobChanges on, re-checking unchanged jobs is free. You pay only for jobs that changed.

Output fields

FieldDescription
id, jobPostId, urlJob identifiers and the public job page
title, categories, skills, keySkillsRole, MCF categories, all listed skills, and the skills the employer marked as key
companyName, companyUen, postedCompanyNameHiring company, its UEN, and the posting agency if different
companyWebsite, companyLogoUrl, companyEmployeeCountCompany website, logo image URL and headcount (when MCF has them)
ssocCode, occupationIdOccupation code (SSOC) and MCF occupation id
ssicCode, ssicDescriptionIndustry code (SSIC 2020) and its description
salaryMin, salaryMax, salaryCurrency, salaryType, isHideSalaryAdvertised salary range, and whether the employer hides it on the site
employmentType, positionLevel, minimumYearsExperience, educationLevelRole terms and requirements (education is decoded from the SSEC code)
flexibleWorkArrangements, workingHours, shiftPatternWorking arrangements, when stated
address, districts, region, lat, lngLocation, district, region and map coordinates
vacanciesNumber of openings
postedAt, originalPostedAt, updatedAt, closingDate, statusPosting dates and status
numberOfApplications, views, repostCount, editCountEngagement and posting history reported by MCF
isPostedOnBehalftrue when an agency posted on behalf of the hiring company
descriptionText, descriptionHtmlJob description as plain text (always), and raw HTML (only with includeDescription)
source, scrapedAtProvenance

Notes

  • Every job gets a detail request. Up to about 6 run at a time, with exponential backoff on HTTP 429 and 5xx responses.
  • Results are deduplicated by job ID within a run.

This Actor reads publicly available job listings. It does not log in or access private data. It is not affiliated with MyCareersFuture, Workforce Singapore or the Singapore Government. You are responsible for making sure your use of the data complies with the MyCareersFuture terms of use, Singapore's PDPA and any other law that applies to you.

Support

Found a bug or need a field that is missing? Open an issue on the Actor's Issues tab.