JobStreet Job Scraper - Deduplicated, Pay Once Per Job (SEA)
Pricing
Pay per event
JobStreet Job Scraper - Deduplicated, Pay Once Per Job (SEA)
Scrape JobStreet jobs in Malaysia, Singapore, Philippines and Indonesia: title, company, salary, full description, applicants, employer industry. Complete past the 550-result wall, deduplicated across runs, billed once per job. Also covers SEEK and JobsDB.
Pricing
Pay per event
Rating
0.0
(0)
Developer
Automation Craft
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
Get every matching job from JobStreet (my.jobstreet.com, sg.jobstreet.com, ph.jobstreet.com and id.jobstreet.com) as clean JSON, CSV or Excel: title, employer, salary, full description, applicant numbers, employer industry and size, exact posting dates and structured locations. Built to be complete and fair:
- Complete. JobStreet stops every search at 550 results, even when it reports thousands. This Actor detects that wall and automatically splits the search (by sub-category, work type, salary band and region) until every matching job is reached. Most other scrapers silently return the first 550.
- Deduplicated, billed once. Duplicates inside a run are removed. Give your search a memory name and jobs you already received are skipped in every later run. You never pay twice for the same job.
- Filter by employer, not just by job. Industry (the site's own employer taxonomy), employer name, rating, recruitment agencies on or off, private advertisers on or off.
- Honest about what you get. Every run ends with a summary of coverage and how often each field was populated. The table below tells you what to expect per market before you spend a cent.
Also covers SEEK (Australia, New Zealand) and JobsDB (Hong Kong, Thailand): pick any of the eight markets in the "Countries" dropdown. If you mostly need those markets, the sibling listings JobStreet Job Scraper and JobsDB Job Scraper are the same engine with those defaults.
30-second start
- Pick Countries (🇲🇾 Malaysia, 🇸🇬 Singapore, 🇵🇭 Philippines, 🇮🇩 Indonesia are preselected) and, if you like, Locations from the list or type your own ("Kuala Lumpur").
- Pick Job categories (for example "Marketing & Communications") and/or type Keywords ("digital marketing").
- Optional: Employer industries (for example "Online Media & eCommerce", "Specialty Retail").
- Choose Posted within (last 24 hours, 3, 7, 14 or 30 days).
- Give it a Memory name if you will run it again and only want new jobs.
- Start. Download JSON, CSV or Excel from the Dataset tab, or read it through the API.
Prices: $0.60 per 1,000 jobs found, plus $0.30 per 1,000 for full job details and $0.10 per 1,000 for employer profiles (only when the employer actually has one). A complete record therefore costs $1.00 per 1,000 jobs. Duplicates, filtered-out jobs and empty profiles are free. There is no start fee.
What you get, per market
| Australia | New Zealand | Malaysia, Singapore, Philippines, Indonesia | Hong Kong, Thailand | |
|---|---|---|---|---|
| Job title, employer, teaser, bullet points, category, work type, listing date, URL | always | always | always | always |
| Full description (HTML, text, Markdown, sections) | always with job details | always | always | always |
| Salary shown on the ad, parsed to min / max / period / currency | 56% of ads show a salary; usually per year, often "+ super" | similar to Australia | most ads show a salary, usually per month (RM, S$, PHP, Rp) | many ads show a salary per month (HK$, THB) |
| Applicant count, share with resume and cover letter | appears a few hours after posting; 97% of ads | same | same | same |
| Employer industry, size, website, rating, reviews | 61% of ads link to an employer profile | similar | similar; profiles are common for larger employers | similar |
| Suburb / district, region, state | yes | yes (region) | yes (state or region) | yes (district and area) |
| Postcode | 96% of ads | 64% of ads | not published on the site | not published on the site |
| On-site / hybrid / remote | when declared by the advertiser | same | same | same |
| Screening questions | when the advertiser uses the site's apply flow | same | same | same |
| Labels in the local language | n/a | n/a | Indonesia: yes (set Label language) | Thailand and Hong Kong: yes |
Things this Actor deliberately does not do: it does not reveal salary ranges the advertiser chose to hide, does not collect recruiter contact details from profile pages, does not log in or touch anything behind a login, and does not cover Zhaopin (China), which runs on a different platform.
How the filters map to the site
| Input | What it does |
|---|---|
| Countries | Which sites to search. Each country is one dataset; results carry market, country and brand. |
| Locations | Regions and cities exactly as the site names them (dropdown), or anything you would type into the site's location box. Unresolved entries appear in unresolvedLocations in the run summary. |
| Job categories / sub-categories | The site's classification taxonomy (30 categories, 394 sub-categories). Labels or ids both work through the API. |
| Keywords | The site's keyword search. |
| Work type, work arrangement, salary from/to | The site's own filters. The salary filter also matches ads that hide their salary. |
| Posted within | 1 / 3 / 7 / 14 / 30 days use the site's filter. Any other number of days through the API is applied exactly. postedAfter / postedBefore are exact ISO timestamps. |
| Employer industries | Matched against the employer's company profile. Decide with "Employers without a known industry" whether profile-less employers are excluded (precise) or included (complete). |
| Must contain / must not contain | Plain-text filters over title, teaser, bullets, employer and (with job details) the full description. |
| Search URLs | Paste any search, job or company URL from SEEK, JobStreet or JobsDB (old or new domains). |
| Memory name | The key that makes repeat runs return only new jobs. |
Output
One item per job. Nested objects for developers (salary, classifications, descriptionSections) and flat fields for spreadsheets (salaryMin, salaryMax, state, postcode, companyIndustry...). The last item of every run is a run-summary with coverage, fill rates, filter counts and charges.
Most useful fields:
| Field | Meaning |
|---|---|
id, url, market, country, brand | Identity. sourceMarket shows where a cross-listed ad originated. |
title, normalisedRoleTitle, teaser, bulletPoints, descriptionText, descriptionHtml, descriptionMarkdown, descriptionSections | The ad. |
listedAt, createdAt, updatedAt, expiresAt | ISO timestamps (UTC). |
classification, subclassification (+ ids) | The site's job taxonomy. |
location, suburb, area, city, state, stateCode, postcode, locationHierarchy | Structured location. |
workType, workArrangement | Full time / part time / contract / casual; on-site / hybrid / remote. |
salaryLabel, salaryMin, salaryMax, salaryPeriod, salaryCurrency, salary.includesSuper, salary.parseConfidence, salary.annualisedMin/Max | Salary as shown and as parsed. |
applicantCount, applicantsWithResumePct, applicantsWithCoverLetterPct, applicantVolume | Demand signals. |
advertiserName, advertiserId, advertiserIsVerified, isPrivateAdvertiser, isRecruitmentAgency | Who posted it. |
companyName, companyIndustry, companySize, companyWebsite, companyPrimaryLocation, companyDescription, companyRating, companyReviewCount, companyAwards, companyProfileUrl, companyLogoUrl, companyHasProfile | The employer. |
screeningQuestions, isLinkOut, isSponsored, isFeatured, tags | Application details and ad flags. |
ecommerceSignals, seniority, detectedSkills, visaSponsorship, isRemoteFriendly | Derived signals from the text. |
emails, phones | Only when "Extract emails and phone numbers" is on. |
changeType, isDuplicate, firstSeenAt, lastSeenAt, contentHash, searchShard | Dedup and provenance. |
Sample item from a live run:
{"id": "94222698","url": "https://my.jobstreet.com/job/94222698","shareUrl": "https://my.jobstreet.com/job/94222698?tracking=SHR-WEB-SharedJob-asia-5","market": "MY","countryCode": "MY","country": "Malaysia","brand": "JobStreet","sourceMarket": "MY","title": "Marketing Executive","normalisedRoleTitle": "Marketing Executive","teaser": "Plan and execute social media campaigns, recruit influencers and affiliates, and support offline marketing activities.","bulletPoints": ["Competitive salary with big fat bonuses !","Support dynamic team in innovative business solutions !","Real growth, not just talk - you’ll get hands-on exposure !"],"descriptionText": "About the role\nThis role involves managing social media content across multiple platforms, executing marketing campaigns, and supporting product launches and promotional activities. You will coordinate content creation, monitor performance metrics, conduct market research, and maintain campaign documentation.\nKey responsibilities\n- Plan and schedule social media content across Instagram, TikTok, a ...","status": "Active","isExpired": false,"isLinkOut": false,"isFeatured": false,"isSponsored": false,"adType": "ORGANIC","displayTags": [],"tags": [],"roleId": "marketing-executive","hasRoleRequirements": true,"screeningQuestions": ["How many years' experience do you have as a Business Operations Executive?","Are you willing to undergo a pre-employment background check?"],"videoUrl": null,"listedAt": "2026-08-26T11:40:43.598Z","listedAtDisplay": "4d ago","createdAt": "2026-08-26T11:40:18.295Z","updatedAt": "2026-08-26T11:40:43.598Z","expiresAt": "2026-09-25T13:59:59.999Z","classificationId": "6008","classification": "Marketing & Communications","subclassificationId": "6009","subclassification": "Brand Management","classifications": [{"classificationId": "6008","classification": "Marketing & Communications","subclassificationId": "6009","subclassification": "Brand Management"}],"location": "Petaling Jaya, Selangor","locationLabel": "Petaling Jaya, Selangor","suburb": "Petaling Jaya","area": null,"city": "Petaling","state": "Selangor","stateCode": null,"postcode": null,"locationHierarchy": ["Petaling Jaya Selangor","Selangor"],"workType": "Full time","workTypes": ["Full time"],"workTypeId": 242,"workArrangement": "On-site","workArrangements": ["On-site"],"salary": {"label": "RM 4,000 – RM 4,500 per month","currency": "MYR","min": 4000,"max": 4500,"period": "month","includesSuper": null,"isDisclosed": true,"parseConfidence": 0.85,"annualisedMin": 48000,"annualisedMax": 54000},"salaryLabel": "RM 4,000 – RM 4,500 per month","salaryMin": 4000,"salaryMax": 4500,"salaryCurrency": "MYR","salaryPeriod": "month","applicantCount": 141,"applicantsWithResumePct": 100,"applicantsWithCoverLetterPct": 29,"applicantVolume": "high","advertiserId": "63022078","advertiserName": "Glowith Global Sdn Bhd","advertiserIsVerified": true,"advertiserRegistrationDate": "2025-04-23T11:49:39.338Z","isPrivateAdvertiser": false,"isRecruitmentAgency": false,"companyName": "Glowith Global Sdn Bhd","companyId": null,"companySlug": null,"companyProfileUrl": null,"companyJobsUrl": "https://my.jobstreet.com/jobs?companyprofilestructureddataid=3151002","companyLogoUrl": "https://bx-branding-gateway.cloud.seek.com.au/6e76a485-8ff9-4ac5-ab4a-7c64f6a3074f.1/jdpLogo","companyCoverUrl": "https://image-service-cdn.seek.com.au/080a89f74c544035b8da82afbb6b9db52c37bcb9/8f50f8545b48866f30b0f8b02b06fdae349eb650","companyIndustry": null,"companyIndustryRaw": null,"companySize": null,"companyWebsite": null,"companyPrimaryLocation": null,"companySpecialities": null,"companyDescription": null,"companyRating": null,"companyReviewCount": null,"companySalaryRating": null,"companyAwards": [],"companyHasProfile": false,"companyOrgId": "3151002","phoneNumberOnAd": null,"ecommerceSignals": ["e-commerce","marketplace"],"seniority": "mid","detectedSkills": ["TikTok","Canva","social media","influencer"],"visaSponsorship": null,"isRemoteFriendly": false,"detailFetched": true,"companyProfileFetched": false,"contentHash": "e6079cec68327d39","searchShard": "root/sub6009","searchRank": 1,"isDuplicate": false,"changeType": "NEW","firstSeenAt": "2026-08-31T08:54:14.180Z","lastSeenAt": "2026-08-31T08:54:14.180Z","scrapedAt": "2026-08-31T08:54:14.180Z"}
Using the API
Same input as the form. Ids and labels are interchangeable.
curl -X POST "https://api.apify.com/v2/acts/automation_craft~jobstreet-job-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"markets": ["MY"],"classifications": ["6008"],"postedWithinDays": "7","companyIndustries": ["Online Media & eCommerce", "Specialty Retail"],"unknownIndustryPolicy": "exclude","dedupMemoryName": "ecommerce-marketing-weekly","includeDetails": true,"includeCompanyProfile": true,"maxItems": 500}'
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('automation_craft/jobstreet-job-scraper').call({searchUrls: ['https://my.jobstreet.com/digital marketing-jobs'.replace(' ', '-')],postedWithinDays: '3',dedupMemoryName: 'daily-digital marketing'.replace(' ', '-'),});const { items } = await client.dataset(run.defaultDatasetId).listItems();const jobs = items.filter((i) => i.type !== 'run-summary');
from apify_client import ApifyClientclient = ApifyClient(os.environ["APIFY_TOKEN"])run = client.actor("automation_craft/jobstreet-job-scraper").call(run_input={"markets": ["MY"], "keywords": "digital marketing", "postedWithinDays": "7", "maxItems": 200})items = [i for i in client.dataset(run["defaultDatasetId"]).iterate_items() if i.get("type") != "run-summary"]
Scheduling: create a Schedule in Apify (daily or weekly) with a memory name set; each run then delivers only the jobs that appeared since the previous run.
Notes on the 550-result wall
JobStreet returns at most 550 results per distinct search and then silently returns empty pages, no matter how many jobs it says exist. This Actor probes the total, and when a search is over the wall it splits it into narrower searches (sub-category, then work type, then salary band, then region) and merges the results, removing duplicates. The run summary reports slices, uniqueJobsSeen and slicesTruncated (which should be empty). Very broad searches (for example a whole country with no filters) can take a few minutes; narrow them with a category or a time window when you can.
Fair use
This Actor reads publicly available listings and the public employer profiles the site publishes, at a polite request rate (4 per second by default). It never logs in. Use the data in line with the site's terms and the laws that apply to you.
Support
Something missing or wrong? Open an issue on the Actor's Issues tab. Fixes usually ship within a day.