JobStreet Scraper - Jobs, Salaries, Companies & Apply Details
Pricing
from $1.00 / 1,000 results
JobStreet Scraper - Jobs, Salaries, Companies & Apply Details
From $1/1K. Scrape JobStreet listings across Malaysia, Singapore, Indonesia, and the Philippines. Extract titles, companies, salaries, locations, descriptions, company info, and apply details. Search with filters or paste JobStreet URLs directly. Fast and cost-efficient.
Pricing
from $1.00 / 1,000 results
Rating
5.0
(1)
Developer
Abot API
Maintained by CommunityActor stats
2
Bookmarked
29
Total users
2
Monthly active users
a day ago
Last modified
Categories
Share
JobStreet Jobs Scraper: Job Listings Across Malaysia, Singapore, the Philippines and Indonesia
JobStreet Jobs Scraper turns JobStreet into a clean job-search API across all four Southeast Asian markets it runs: Malaysia, Singapore, the Philippines and Indonesia. Search by keywords, location, category, work type, salary and listing date, or paste JobStreet search URLs directly and let the actor read the filters from the link. Get back structured job records with the full HTML description, company overview, salary and any contact details the ad exposes, then export to JSON, CSV or Excel, or pull results straight into your app through the API.
Why This Scraper?
- All four JobStreet country sites from one actor. The country is auto-detected from each pasted URL, or picked from a dropdown when you search by filters.
- Two ways to search. Fill in the filter fields (country, keywords, location, category, work type, salary range, listing date), or paste one or more JobStreet search URLs and mix all four markets in a single run.
- 50-plus fields per job, including the full HTML description, plain-text body, bullet points, salary, company overview, and any phone numbers or emails found in the ad body.
- Detail enrichment is batched. One extra request covers a whole page of up to 22 jobs, not one request per job, so a full run with descriptions costs far fewer requests than fetching each job's page individually.
- Forward pagination across as many pages as you allow, with automatic de-duplication by job ID within a run.
- Filter by category, work type, salary range and listing recency, in filter mode or through the URL itself.
- Global caps on item count and run time, so a run never overshoots your budget, and whatever was already fetched is always saved even if a cap or deadline stops the run early.
Use Cases
- Job boards and aggregators: mirror JobStreet listings into your own board or app across all four markets.
- Recruiting and sourcing teams: monitor new roles in a category or location and route them into a pipeline or CRM.
- Salary and market research: build salary benchmarks by market, category and work type from the structured salary and classification fields.
- Lead generation and outreach: collect contact phone numbers and emails that employers left directly in the ad body.
- Company intelligence: track a company's open roles and hiring pace over time.
- Labor market analytics: build historical datasets of job counts, categories and locations across Malaysia, Singapore, the Philippines and Indonesia.
Data You Get
Sample shape: values are illustrative placeholders, not from a live listing.
| Field | Example |
|---|---|
id | "00000001" |
url | "https://my.jobstreet.com/job/00000001" |
applyLink | "https://my.jobstreet.com/job/00000001/apply" |
title | "Software Engineer" |
teaser | "Join a growing team building cloud services." |
companyName | "Sample Company Sdn Bhd" |
companyOverview | "Sample Company is a leading provider of cloud services in the region." (when includeFullDescription is on) |
advertiserName | "Sample Company Sdn Bhd" |
locationLabel | "Kuala Lumpur" |
countryCode | "MY" |
classificationInfo | { "classification": "Information & Communication Technology", "subClassification": "Developers/Programmers" } |
workTypes | ["Full time"] |
salaryLabel | "RM 5,000 to RM 8,000 per month" |
content | "<p>Full job description HTML.</p>" (when includeFullDescription is on) |
contentText | "Full job description, plain text." (when includeFullDescription is on) |
bulletPoints | ["Competitive salary", "Hybrid work", "Career growth"] |
phoneNumbers | ["+60100000000"] (when includeFullDescription is on) |
emails | ["careers@example.com"] (when includeFullDescription is on) |
listingDate | "2026-01-01T00:00:00Z" |
listingDateDisplay | "2d ago" |
expiresAt | "2026-02-01T00:00:00Z" (when includeFullDescription is on) |
isVerified | true (when includeFullDescription is on) |
detailFetched | true |
scrapedAt | "2026-01-01T00:00:00.000Z" |
The full record carries more than this table: classifications[] with category IDs, workArrangementLabels, salaryCurrency, shareLink, companyOpenJobs, branding, advertiser details, and raw passthrough blocks (advertiserRaw, employerRaw, companyProfileRaw) so no upstream field is dropped. content, contentText, contentSections, companyOverview, companyIndustry, companySize, companyWebsite, companyPerks, companyReviewCount, companyReviewRating, companyCoverImageUrl, expiresAt, isVerified, salaryCurrency, phoneNumbers and emails only come from the detail fetch and stay empty when includeFullDescription is off (salaryCurrency is read straight from the site and is only returned for listings whose currency differs from the market's own, so it is often empty even with the detail fetch on; the symbol in salaryLabel always shows the currency), while detailFetched tells you, per job, whether that fetch actually succeeded. When incrementalMode is on, every row also carries changeType, changedFields, firstSeenAt and lastSeenAt, and a job that drops out of a fully scanned search can appear as a synthesized EXPIRED row built from its last known snapshot, see "Resume and recurring updates" below for exactly when that happens.
How to Use
- Pick how you want to search: fill in the filter fields (country, keywords, location, category, work type, salary, listing date) under Option 1, or paste one or more JobStreet search URLs under Option 2. If you set
urls, every Option 1 field is ignored, and the country and filters come from each URL instead. - Turn
includeFullDescriptionon to get the full HTML description, company overview, expiry date and phone number for each job. Leave it off to get only what the search results themselves already carry, without the extra per-page request. - Set
maxItemsand, optionally,maxTimeSecto cap the size and length of the run, then click Start. - Download the dataset as JSON, CSV or Excel, or read it through the API.
Basic search (Malaysia):
{"country": "MY","keywords": "software engineer","location": "Kuala Lumpur","maxItems": 50}
Search with filters (Singapore, ICT, full time, salary range):
{"country": "SG","keywords": "data engineer","classification": ["6281"],"workType": ["242"],"salaryMin": 5000,"salaryMax": 12000,"salaryType": "monthly","daterange": 14,"sortmode": "ListedDate","maxItems": 100,"includeFullDescription": true}
Multiple countries via URL mode:
{"urls": ["https://my.jobstreet.com/it-jobs/in-Penang","https://sg.jobstreet.com/jobs-in-information-communication-technology","https://ph.jobstreet.com/accountant-jobs","https://id.jobstreet.com/marketing-jobs/in-Jakarta-Raya"],"maxItems": 200,"includeFullDescription": false}
Recent jobs only, sorted by date:
{"country": "ID","keywords": "marketing","daterange": 7,"sortmode": "ListedDate","maxItems": 30}
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/jobstreet-scraper").call(run_input={"country": "MY","keywords": "software engineer","location": "Kuala Lumpur","maxItems": 50,})for job in client.dataset(run["defaultDatasetId"]).iterate_items():print(job["title"], job["companyName"], job["salaryLabel"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/jobstreet-scraper').call({country: 'MY',keywords: 'software engineer',location: 'Kuala Lumpur',maxItems: 50,});const { items } = await client.dataset(run.defaultDatasetId).listItems();
Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.
How caps shape a run
maxItems is a single budget shared across every URL and every page, not a per-URL limit: with 3 URLs and maxItems=50, the actor paginates the first URL until the budget is used up, and only moves to the second and third URL if room remains. Set maxItems to 0 for no cap. maxTimeSec is a wall-clock budget: once it elapses, the actor stops paginating, flushes whatever it already fetched, and ends the run cleanly instead of losing that work. Leaving both maxItems and maxTimeSec at 0 runs until the search itself runs out of pages, so set at least one of them for a predictable run.
Resume and recurring updates
Resume (resumeFromRunId) continues one interrupted run: paste its run ID or dataset ID and the actor skips every job it already collected there, so a retried run adds only what is still missing.
Incremental mode (incrementalMode) is for a search you run on a schedule against the same filters or URLs. Turn it on and the actor remembers what that exact search returned last time, keyed by stateKey (or an automatic key derived from your filters, so two differently configured searches never share a baseline by accident). Every job scraped this run is then classified:
NEW: not seen in a previous run.UPDATED: content changed since last time, withchangedFieldsnaming exactly what. Every returned field is compared exceptscrapedAt,listingDateDisplay(the site's relative "N ago" text) anddetailFetched, which change on every fetch without the job changing; a newlistingDate(a genuine relist) does count. Add your own exclusions withignoreFieldsForChanges.UNCHANGED: identical to last time. Suppressed by default; turn onemitUnchangedto also push (and pay for) these rows.EXPIRED: was tracked before and is missing from this run. This only fires when the run reached the natural end of every search it ran, with nomaxItemscap, nomaxTimeSecdeadline, noresumeFromRunIdand no pasted URL starting atpage=2or later cutting it short, since a partial scan cannot tell a job is gone from a job it simply has not reached yet. It also requiresemitExpiredto be on; otherwise the previous state for those jobs is left untouched and nothing is emitted.REAPPEARED: a job that was previously markedEXPIREDshows up again. Because a job can only becomeEXPIREDwhenemitExpiredwas on for a prior complete scan,REAPPEAREDcan only occur under that same condition. If you never turnemitExpiredon, a job that drops out of the results and later comes back is simply classifiedUNCHANGEDorUPDATEDagainst its last snapshot, neverREAPPEAREDorNEW.
Incremental mode is off by default, so existing scheduled runs are unaffected. maxItems still counts rows actually pushed, not rows scanned: if most of a tracked search is UNCHANGED and suppressed, the actor keeps paginating to backfill your budget with jobs that did change.
Send results into your apps (MCP connectors)
Optionally pipe the scraped results into the apps you already use, through Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape. The Apify dataset itself is never changed.
What gets written to the connector: a condensed, human-readable summary of each record, not the full JSON. Each job becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.
- Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the "Pipe results into your apps" input field. If the picker is empty, you have not authorized a connector yet.
- For Notion, also set
notionParentPageUrlto the page where job pages should be created.
The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
country | string | "MY" | Market to search: MY, SG, PH, or ID. Applies in filter mode only. |
keywords | string | none (prefill: "software engineer") | Job title or keywords. Empty matches all jobs in the location. |
location | string | none | Location within the country, for example Kuala Lumpur or Jakarta Raya. Empty searches the whole country. |
classification | array | [] | One or more top-level category IDs. Empty means all categories. |
workType | array | [] | Work types: 242 Full time, 243 Part time, 244 Contract/Temp, 245 Casual/Vacation. |
salaryMin | integer | none | Minimum salary in the local currency. |
salaryMax | integer | none | Maximum salary in the local currency. |
salaryType | string | "monthly" | Whether the salary filter values are monthly or annual. |
daterange | integer | none | Listed within N days. Accepted: 1, 3, 7, 14, 31. Other values are dropped with a warning. |
workArrangement | array | [] | 1 On-site, 2 Hybrid, 3 Remote (applied by the search itself). Ignored in URL mode; there the arrangement comes from a /on-site, /hybrid or /remote path segment or the workarrangement URL query parameter. |
subClassification | array | [] | Sub-category IDs (output subCategoryId, e.g. 6028). Ignored in URL mode. |
includeKeywords | array | [] | Keep only jobs whose title, company, teaser, bullet points or (with full description on) description contain at least one of these. Filtered-out jobs are not delivered and not billed. |
excludeKeywords | array | [] | Drop jobs matching any of these terms (same fields). Not delivered, not billed. |
fromDate | string | none | Post-filter: keep jobs listed on or after this date. |
toDate | string | none | Post-filter: keep jobs listed on or before this date. |
maxAgeMinutes | integer | 0 | Post-filter: keep only jobs listed within the last N minutes (0 = off). |
requireContact | string | off | email, phone, either or both: keep only jobs where a contact was found in the description (needs full description on). |
maxPages | integer | 0 | Stop each search after N pages of 22 jobs (0 = no limit). |
descriptionFormat | string | all | all, text, html or markdown. |
sortmode | string | "ListedDate" | ListedDate newest first, or KeywordRelevance best match. |
urls | array | 13 example URLs shown in the form (one per supported shape and host) | One or more JobStreet URLs (see the supported shapes below). Overrides every filter field above. Country is auto-detected per URL. If you leave urls untouched on its default but set any filter or incremental input to a non-default value (country, keywords, location, classification, subClassification, workType, workArrangement, salaryMin, salaryMax, salaryType, daterange, sortmode, includeKeywords, excludeKeywords, fromDate, toDate, maxAgeMinutes, requireContact, or incrementalMode), the example URLs are ignored and your filter search runs, exactly as before. With every one of those on its default, the run works through the examples in order, and the default maxItems of 20 normally ends it within the first one or two. |
includeFullDescription | boolean | true | Fetch the full HTML description, company overview, expiry date and phone via the job-detail endpoint. Batched per page. |
maxItems | integer | 20 | Global cap across all URLs and pages. 0 means unlimited. |
maxTimeSec | integer | 0 | Global wall-clock cap in seconds. 0 means no limit. Partial results are flushed when the cap is reached. |
resumeFromRunId | string | none | Continue one specific interrupted run. See "Resume and recurring updates" above. |
incrementalMode | boolean | false | Track a scheduled search across runs and classify changes. See above. |
stateKey | string | none | Optional name for the Incremental mode baseline. Auto-derived from your filters when empty. |
emitUnchanged | boolean | false | Also push rows unchanged since the last Incremental mode run. Bills extra rows. |
emitExpired | boolean | false | Push a synthetic row for jobs that dropped out of a fully scanned search. Bills extra rows. |
ignoreFieldsForChanges | array | none | Incremental mode only: field names (or dotted nested paths such as branding.logo) that never trigger UPDATED and never appear in changedFields. They are still returned in every row. Changing the list causes no one-time wave of UPDATED rows. |
proxyConfiguration | object | Apify proxy, default connection group | Proxy settings. See "Plan Requirement" below. |
mcpConnectors | array | none | Optional: send a summary of each job to apps you authorized under Integrations. |
notionParentPageUrl | string | none | Notion connector only: the page under which job pages are created. |
maxNotifyListings | integer | 50 | Cap on items written to each connector per run. Does not affect the dataset. |
Extra output fields (additive): jobId, seekJobId, canonicalUrl, company, location, locationCountry, salaryText, best-effort salaryMin/salaryMax/salaryType parsed from the salary label (numbers, decimals allowed for hourly pay; only figures next to a currency symbol or a range dash count, so a bare "13th month" is ignored; null when the listing shows no figure), employmentType, workArrangement, category/categoryId, subCategory/subCategoryId, description, descriptionHtml, descriptionMarkdown, descriptionLength, contentHash, extractedEmails/extractedPhones/extractedUrls, socialProfiles, contactEmail/contactPhone, isExpired, listingStatus, applyUrl, postedDate, validThrough, isSponsored, companyIndustry/companySize/companyWebsite/companyPerks/companyReviewCount/companyReviewRating/companyCoverImageUrl (company profile, with the detail fetch), sourceUrl/sourceCountry/sourceDomain, searchQuery, searchUrl (the URL you pasted in URL mode; in filter mode a JobStreet search URL built from your filters), fetchedAt, and in incremental mode previousSeenAt, expiredAt and stateKey. Applicant counts and state/suburb/postcode are not exposed by JobStreet publicly.
Output Example
Sample shape: values are illustrative placeholders, not from a live listing.
{"id": "00000001","url": "https://my.jobstreet.com/job/00000001","applyLink": "https://my.jobstreet.com/job/00000001/apply","title": "Software Engineer","teaser": "Join a growing team building cloud services.","companyName": "Sample Company Sdn Bhd","companyId": "00000000","companyOverview": "Sample Company is a leading provider of cloud services in the region.","advertiserName": "Sample Company Sdn Bhd","locationLabel": "Kuala Lumpur","locationSeoHierarchy": ["Kuala Lumpur", "Wilayah Persekutuan"],"countryCode": "MY","classificationInfo": {"classification": "Information & Communication Technology","subClassification": "Developers/Programmers"},"workTypes": ["Full time"],"salaryLabel": "RM 5,000 to RM 8,000 per month","content": "<p>Full job description HTML appears here when includeFullDescription is true.</p>","contentText": "Full job description plain text appears here.","bulletPoints": ["Competitive salary", "Hybrid work", "Career growth"],"phoneNumbers": ["+60100000000"],"emails": ["careers@example.com"],"listingDate": "2026-01-01T00:00:00Z","listingDateDisplay": "2d ago","expiresAt": "2026-02-01T00:00:00Z","isVerified": true,"detailFetched": true,"scrapedAt": "2026-01-01T00:00:00.000Z"}
Plan Requirement
Any Apify plan can run this actor on the default proxy setting. The actor reads JobStreet's job-search data, which answers on Apify's standard datacenter proxies, so the default setting needs no residential proxy and no action from you. Measured: the search data loads on datacenter connections, while JobStreet's own browser-facing web pages are challenged on datacenter and direct connections and mostly load on residential after retries. That is why URL mode never opens the page you paste: it reads the filters from the link and runs the equivalent search (see "Which URL shapes work in URL mode?").
How the connection works, in order:
- The default proxy (your selected groups, or Apify's automatic pool) is tried first.
- If it is refused for your account, the actor moves to Apify residential, then to a backup connection. Residential is only used when your plan includes it.
- A single refused page does not condemn a connection: the actor rotates the exit and retries within a per-request time budget. If one request keeps failing on the default proxy it moves to the next connection for that request only, and the next request starts on the default proxy again. Only the proxy itself refusing your account removes a connection for the rest of the run.
- If you supply your own proxy URLs, only those are used, and there is no fallback beyond them.
The actor never runs without a proxy. If your plan has no proxy access, the log shows this notice and the run continues on the backup connection when it can:
The selected connection is unavailable to this run. Apify free plans do not include residential proxies. Continuing on a backup connection; some pages may still be unavailable. For residential access, upgrade at https://apify.com/pricing or supply your own proxy URLs.
When results were served over the backup connection, the log says: "Served over the backup connection (the default connection was unavailable)."
If no page could be loaded, the run ends as failed with one of these messages rather than reporting an empty result:
- "The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required: https://apify.com/pricing. If you entered your own proxy URLs, check that their credentials are valid."
- "No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested JobStreet pages. Upgrade at https://apify.com/pricing or supply your own proxy URLs, then try again."
- "Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search. Please try again later."
The last one means a connection problem, not an empty search: a search that matches nothing exits cleanly with a status message instead. For very large or frequent runs, the residential group gives more headroom; pick it under Connection and optionally pin the country to the market you scrape.
FAQ
How much does it cost?
You pay per job returned, with the full-detail fetch billed only when includeFullDescription is on, and Incremental mode's emitUnchanged or emitExpired billed only for the extra rows those toggles add. The Pricing tab shows the current rates. Billing is pay-per-event: a one-time Actor Start event per run, one result event per job row delivered to the dataset, and, only when includeFullDescription is on, one Enriched Output event (detail-enrichment) per job whose full description was actually fetched and delivered. Jobs removed by your include/exclude keyword or contact filters, and UNCHANGED rows suppressed in Incremental mode, are neither delivered nor billed. Use maxItems to cap the cost of any run.
Is it legal to scrape JobStreet?
This actor collects only publicly available job listing data. You are responsible for how you use it: follow JobStreet's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Job listings are generally public information, but company logos and branding may carry separate rights.
Can I get only new or changed jobs on a schedule?
Yes. Schedule the actor from the Schedules tab and turn on incrementalMode. Each run then classifies every job as NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED against what the same search returned last time, and unchanged jobs are not billed unless you turn emitUnchanged on.
Why are my filter fields being ignored?
URL mode always overrides filter mode. If urls has any entries, every field under Option 1 (country, keywords, location, category, work type, salary, date range) is ignored, and the actor reads the country and filters from each URL's own path and query string instead. Clear urls to go back to filter search. Behaviour change: the urls default is now one example URL per supported shape, so a run that leaves urls untouched and every other input on its default starts on those examples (the default maxItems of 20 ends it early). As soon as you set any filter field or incrementalMode to a non-default value, the untouched examples are ignored and your filter search runs (and keeps its previous incremental state key), so existing filter-mode callers see no change.
Which URL shapes work in URL mode?
| Shape | Example | Result |
|---|---|---|
| Keyword + location | https://my.jobstreet.com/software-engineer-jobs/in-Kuala-Lumpur | Supported |
| Keywords only | https://my.jobstreet.com/it-jobs | Supported |
| Location only | https://my.jobstreet.com/jobs/in-Selangor | Supported |
| All jobs | https://sg.jobstreet.com/jobs | Supported |
| Category page | https://my.jobstreet.com/jobs-in-information-communication-technology | Supported |
| Category + location | https://sg.jobstreet.com/jobs-in-accounting/in-Singapore | Supported |
| Category + sub-category | https://my.jobstreet.com/jobs-in-information-communication-technology/developers-programmers | Supported |
Work arrangement (on-site, hybrid, remote) | https://my.jobstreet.com/software-engineer-jobs/remote, /jobs-in-information-communication-technology/remote | Supported: mapped to the work-arrangement filter (on-site 1, hybrid 2, remote 3) |
Work type (full-time, part-time, contract-temp, casual-vacation) | https://my.jobstreet.com/software-engineer-jobs/full-time, /jobs-in-accounting/full-time | Supported: mapped to the work-type filter |
| Canonical keyword + category form the site redirects to | https://my.jobstreet.com/software-engineer-jobs-in-information-communication-technology/in-Kuala-Lumpur/full-time | Supported: keyword, category, location and work type are all read |
| Filtered query form | https://my.jobstreet.com/jobs?classification=6281&worktype=242&daterange=7&sortmode=ListedDate&page=2 | Supported; keywords, where, classification, subclassification, worktype, workarrangement, salaryrange, salarytype, daterange, sortmode, page are read |
| Search API link | https://my.jobstreet.com/api/jobsearch/v5/search?where=Kuala+Lumpur&keywords=software+engineer | Supported; the same parameters are read |
| Single-job share link | https://my.jobstreet.com/jobs?jobId=95266214 | Not supported: skipped with a warning (it points at one job, and running the surrounding search would return different jobs). Remove ?jobId= to run the search |
| Job detail page | https://my.jobstreet.com/job/95266214 | Not supported: skipped with a warning in the log |
| Company pages | https://my.jobstreet.com/companies, /companies/<slug> | Not supported: skipped with a warning in the log |
A path that does not match one of these shapes, or a category or sub-category name the actor does not know, is skipped with a warning naming the problem; it is never turned into a different search.
Hosts my, sg, ph and id are all accepted. A ?page=2 start page is honoured and counts as a partial scan, so no jobs are marked EXPIRED.
Why did my run fail instead of returning an empty dataset?
A search that legitimately matches nothing exits cleanly with a status message explaining why, and pushes no billable row, so "no jobs found" is never confused with a broken run. A run actually fails, instead, when resumeFromRunId points at a run or dataset ID that cannot be read, or when incrementalMode and resumeFromRunId are combined on a search that already has saved Incremental mode state: the actor stops with a clear message telling you to drop one of the two rather than silently mixing them.
What views does the dataset have?
The dataset has three table views in the Apify Console: Jobs Overview (title, company, location, salary, listed, URL), Job Details (title, company, company overview, description, highlights, emails, phones, apply link, URL) and Incremental Changes (title, change type, changed fields, first and last seen, URL). Each run also stores a run summary under the OUTPUT key of its key-value store.
Can I use it with AI agents or MCP?
Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.
🔗 Want more JobStreet data?
Pair this actor with these related scrapers from the same team:
| 📇 JobStreet From $1/1K. Pull JobStreet company profiles and employee reviews across Malaysia... | 💼 Jora Jobs Scraper Scrape Jora.com job listings across supported countries by keyword, filters, or URL... |
| 💼 Monster Jobs Scraper Scrape Monster.com job listings from search and direct job URLs. Extract full... | 💼 SEEK Jobs Scraper From $0.7/1K. Scrape SEEK.com.au and SEEK.co.nz jobs by keyword, location, or filters... |
| 💼 SimplyHired From $1/1K. Pull active SimplyHired jobs across the US, UK, Canada, Australia, Ireland... | 💼 NIJobs Scraper Scrape NIJobs.com listings across Northern Ireland by keyword, location, salary, posted... |
💬 Support
- 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
- 🛠️ Need another site, extra fields or a private build? Email contact@abotapi.com.
- ⭐ Enjoying it? A quick review on the actor page helps other users find it.