JobStreet / JobsDB / SEEK Jobs Scraper
Pricing
from $0.35 / 1,000 results
JobStreet / JobsDB / SEEK Jobs Scraper
Scrapes job listings with full descriptions from JobStreet (ID/MY/PH/SG), JobsDB (TH/HK) and SEEK (AU/NZ) — keyword and location search with work-type, salary and date filters, plus direct job-URL lookup.
Pricing
from $0.35 / 1,000 results
Rating
0.0
(0)
Developer
Ibnu Adzim
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
5 hours ago
Last modified
Categories
Share
Extract job listings — with the complete job description — from JobStreet (Indonesia, Malaysia, Philippines, Singapore), JobsDB (Thailand, Hong Kong) and SEEK (Australia, New Zealand). One actor, eight markets, one output shape.
Why use this actor
- No account, no login, no API key. Point it at a keyword and run.
- Eight countries from one actor. Pick the market from a dropdown — the data comes back in the same shape every time, so a multi-country pipeline is one schedule instead of eight.
- Full job ads, not just cards. Every row can carry the complete description, the employer's screening questionnaire, benefit bullets, advertiser identity and the exact salary band the employer published.
- Filters that match the site's own: keyword, location, work type, on-site/hybrid/remote, salary range, industry classification, and "posted in the last N days" — ideal for a scheduled run that only picks up new postings.
- Direct job lookup. Already have job URLs or IDs? Feed them in and skip search entirely — useful for re-checking whether a role is still open.
- Stable JSON for pipelines. Every input always produces at least one row, including a labelled row when something goes wrong, so joins downstream never silently lose records. Export to JSON, CSV or Excel.
How it works
- You choose a market and give it search keywords (and optionally a location and filters), or a list of job URLs.
- The actor runs each keyword as its own search and pages through the results until it hits your item cap or the listings run out.
- If full descriptions are enabled, it then fetches the complete ad for every job it found.
- Each job is written to the dataset as one row, together with a summary row per search telling you how many matches the site reported and whether your location filter was understood.
Retries and back-off are handled for you. There are no scrapers, browsers or blocks to babysit.
Input
{"country": "ID","keywords": ["data analyst"],"location": "Jakarta","maxItemsPerQuery": 100,"includeJobDetails": true,"sortBy": "ListedDate","postedWithinDays": 7,"workTypes": ["Full time"],"workArrangements": ["Remote", "Hybrid"],"salaryMin": 10000000,"salaryType": "monthly","maxConcurrency": 4}
| Field | Type | Description |
|---|---|---|
country | string | Market to search: ID, MY, PH, SG (JobStreet), TH, HK (JobsDB), AU, NZ (SEEK). Default ID. |
keywords | array | One search per entry. Leave empty to browse everything in the market. |
location | string | Optional location, e.g. Jakarta, Indonesia, Kuala Lumpur, Sydney. |
jobUrls | array | Scrape specific ads directly — a full job URL or a bare numeric job ID. Can be combined with a keyword search. |
maxItemsPerQuery | integer | Stop each search after this many jobs. 0 = unlimited. Default 100. |
includeJobDetails | boolean | Fetch the full description for every result. Turn off for a fast listing-only crawl. Default true. |
sortBy | string | KeywordRelevance (default) or ListedDate (newest first). |
postedWithinDays | integer | Only jobs listed in the last N days — 1 for the last 24 hours, 7 for the last week. Any day count works. 0 = any date. |
workTypes | array | Any of Full time, Part time, Contract/Temp, Casual/Vacation. |
workArrangements | array | Any of On-site, Hybrid, Remote. |
classificationIds | array | Industry classification IDs, e.g. 1209 (Engineering). Every returned job carries its own IDs, so run once without this to discover them. |
salaryMin / salaryMax | integer | Salary bounds in local currency. Setting either excludes ads published without a salary. |
salaryType | string | monthly (Asian markets) or annual (AU/NZ). |
maxConcurrency | integer | Requests in flight at once. Default 4. |
proxyConfiguration | object | Optional. Residential is recommended for large or scheduled runs. |
Direct job lookup
{"country": "ID","jobUrls": ["https://id.jobstreet.com/job/93908556","93911766"],"includeJobDetails": true}
Output
Every row carries recordType: JOB for a job, SEARCH_SUMMARY once per
search, ERROR when an input could not be processed.
JOB — real output, truncated for length
{"_input": "ID | keywords='data analyst' | where='Jakarta'","_source": "S1-search+S2-job-detail","_scrapedAt": "2026-08-11T16:20:57Z","recordType": "JOB","country": "ID","brand": "JobStreet","jobId": "93911766","jobUrl": "https://id.jobstreet.com/job/93911766","searchContext": { "keywords": "data analyst", "where": "Jakarta", "page": 1, "rank": 1 },"title": "Data Analyst - Staff","companyName": "Erajaya","advertiser": { "id": "60216256", "description": "Erajaya Group" },"employer": {"id": "519523","name": "Erajaya","companyId": "176596129818055","companyUrl": "https://id.jobstreet.com/companies/erajaya-176596129818055"},"classifications": [{"classification": { "id": "6251", "description": "Administration & Office Support" },"subclassification": { "id": "6255", "description": "Data Entry & Word Processing" }}],"locations": [{ "label": "Jakarta", "countryCode": "ID", "seoHierarchy": [{ "contextualName": "Jakarta" }] }],"salaryLabel": "","workTypes": ["Full time"],"workArrangements": { "data": [{ "id": "1", "label": { "text": "On-site" } }] },"listingDate": "2026-08-11T14:05:39Z","listingDateDisplay": "2h ago","teaser": "Advance in data formulation in Excel\nHaving exposure to SQL will be an advantage\ncapable of speaking in English","roleId": "Data-Analyst-Staff","isFeatured": false,"jobDetails": {"job": {"id": "93911766","title": "Data Analyst - Staff","abstract": "Advance in data formulation in Excel\nHaving exposure to SQL will be an advantage…","content": "<div><div><p>Job Description</p></div></div>\n<div><div><ul>\n<li>Make weekly, monthly, quarterly & yearly reports using Canva/ PowerPoint</li>\n<li>Doing Analytical & insights for the department</li>\n<li>Helping the team with administration, especially in relation to payment & purchase</li>\n</ul></div></div>\n<div><div><p>Job Requirements</p></div></div>…","status": "Active","isExpired": false,"expiresAt": { "dateTimeUtc": "2026-08-31T14:05:00.000Z" },"listedAt": { "dateTimeUtc": "2026-08-11T14:05:39.000Z", "label": "2h ago" },"salary": null,"workTypes": { "label": "Full time" },"location": { "label": "Jakarta" },"advertiser": { "id": "60216256", "name": "Erajaya Group", "isVerified": null },"classifications": [{ "label": "Data Entry & Word Processing (Administration & Office Support)" }],"products": { "branding": null, "bullets": null, "questionnaire": null },"shareLink": "https://id.jobstreet.com/job/93911766?tracking=SHR-WEB-SharedJob-asia-4"},"companySearchUrl": "https://id.jobstreet.com/Erajaya-jobs/at-this-company","companyTags": []}}
| Field | Type | Description |
|---|---|---|
jobId / jobUrl | string | Job identifier and its public page. |
title, companyName | string | Role title and the employer name shown in results. |
advertiser, employer | object | Who posted the ad, plus the employer's company page when it has one. |
classifications | array | Industry and sub-industry, with the IDs you can feed back into classificationIds. |
locations | array | Location label, country code, and the location hierarchy. |
salaryLabel | string | Salary exactly as the employer published it (empty when undisclosed). |
workTypes, workArrangements | array/object | Full time / Part time / Contract, and On-site / Hybrid / Remote. |
listingDate, listingDateDisplay | string | Exact posting timestamp, plus the site's relative label. |
teaser | string | The short summary shown in search results. |
searchContext | object | Which keyword, location, page and rank produced this row. |
jobDetails.job.content | string | The complete job ad as HTML. Present when includeJobDetails is on. |
jobDetails.job.products.questionnaire | object | The employer's screening questions, when the ad has them. |
jobDetails.job.products.bullets | array | Benefit/perk bullets from the ad. |
jobDetails.job.expiresAt, status, isExpired | — | Whether the role is still open and when it closes. |
jobDetails.companySearchUrl | string | Link to every other open role at the same company. |
SEARCH_SUMMARY
{"_input": "ID | keywords='data analyst' | where='Jakarta'","recordType": "SEARCH_SUMMARY","country": "ID","brand": "JobStreet","host": "id.jobstreet.com","totalCount": 1423,"returnedCount": 2,"pagesFetched": 1,"locationResolved": true,"resolvedLocation": {"description": "Jakarta","type": "State","whereId": "2030500","localisedDescriptions": { "en": { "contextualName": "Jakarta" }, "id": { "contextualName": "Jakarta Raya" } }}}
| Field | Type | Description |
|---|---|---|
totalCount | integer | How many matches the site reports for this search. |
returnedCount | integer | How many jobs this run actually collected. |
pagesFetched | integer | How many result pages were read. |
locationResolved | boolean | Whether your location was understood. Check this first if a search returns nothing — an unrecognised place name returns zero results rather than an error. |
resolvedLocation | object | The exact place the site matched your text to. |
ERROR
One row per input that could not be processed, so nothing disappears
silently: _error is one of invalid_input, detail_fetch_failed,
fetch_failed, unexpected_shape, upstream_error, and _errorDetail
explains it in plain text.
Notes and limits
- Search depth. The site caps its own result window at roughly 6,000 jobs
per query, no matter how many matches it reports. To go deeper, split a
broad search into several narrower ones (by location, classification, or
postedWithinDays) instead of raisingmaxItemsPerQuery. totalCountis approximate. It is the site's own headline number and runs slightly ahead of the distinct jobs actually served — a search reporting 126 returned 122 unique roles.returnedCountis the honest one.- Several keywords may return the same job. Each keyword is a separate
search with its own rows, so a role matching two keywords appears twice with
a different
searchContext. Deduplicate onjobIdif you want one row per role. - Salary is only as good as the ad. Many employers publish no salary;
those rows have an empty
salaryLabel. SettingsalaryMin/salaryMaxexcludes them entirely. - Speed. Listing-only runs are fast (100 jobs per request). Turning on
full descriptions adds one request per job — raise
maxConcurrencyfor large runs, and lower it if the log starts showing rate limiting. - A proxy is optional. Residential is recommended for large or scheduled runs.
Related actors
| Actor | What it does |
|---|---|
agoda-reviews-scraper | Guest reviews for any Agoda hotel |
booking-reviews-scraper | Guest reviews for any Booking.com property |
tripcom-reviews-scraper | Guest reviews for any Trip.com hotel |
getyourguide-reviews-scraper | Traveller reviews for GetYourGuide activities |
viator-reviews-scraper | Traveller reviews for Viator tours |
holidaycheck-reviews-scraper | Guest reviews for HolidayCheck hotels |
priceline-reviews-scraper | Guest reviews for Priceline hotels |