JobStreet / JobsDB / SEEK Jobs Scraper avatar

JobStreet / JobsDB / SEEK Jobs Scraper

Pricing

from $0.35 / 1,000 results

Go to Apify Store
JobStreet / JobsDB / SEEK Jobs Scraper

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

Ibnu Adzim

Maintained by Community

Actor 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

  1. You choose a market and give it search keywords (and optionally a location and filters), or a list of job URLs.
  2. 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.
  3. If full descriptions are enabled, it then fetches the complete ad for every job it found.
  4. 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
}
FieldTypeDescription
countrystringMarket to search: ID, MY, PH, SG (JobStreet), TH, HK (JobsDB), AU, NZ (SEEK). Default ID.
keywordsarrayOne search per entry. Leave empty to browse everything in the market.
locationstringOptional location, e.g. Jakarta, Indonesia, Kuala Lumpur, Sydney.
jobUrlsarrayScrape specific ads directly — a full job URL or a bare numeric job ID. Can be combined with a keyword search.
maxItemsPerQueryintegerStop each search after this many jobs. 0 = unlimited. Default 100.
includeJobDetailsbooleanFetch the full description for every result. Turn off for a fast listing-only crawl. Default true.
sortBystringKeywordRelevance (default) or ListedDate (newest first).
postedWithinDaysintegerOnly 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.
workTypesarrayAny of Full time, Part time, Contract/Temp, Casual/Vacation.
workArrangementsarrayAny of On-site, Hybrid, Remote.
classificationIdsarrayIndustry classification IDs, e.g. 1209 (Engineering). Every returned job carries its own IDs, so run once without this to discover them.
salaryMin / salaryMaxintegerSalary bounds in local currency. Setting either excludes ads published without a salary.
salaryTypestringmonthly (Asian markets) or annual (AU/NZ).
maxConcurrencyintegerRequests in flight at once. Default 4.
proxyConfigurationobjectOptional. 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 &amp; yearly reports using Canva/ PowerPoint</li>\n<li>Doing Analytical &amp; insights for the department</li>\n<li>Helping the team with administration, especially in relation to payment &amp; 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": []
}
}
FieldTypeDescription
jobId / jobUrlstringJob identifier and its public page.
title, companyNamestringRole title and the employer name shown in results.
advertiser, employerobjectWho posted the ad, plus the employer's company page when it has one.
classificationsarrayIndustry and sub-industry, with the IDs you can feed back into classificationIds.
locationsarrayLocation label, country code, and the location hierarchy.
salaryLabelstringSalary exactly as the employer published it (empty when undisclosed).
workTypes, workArrangementsarray/objectFull time / Part time / Contract, and On-site / Hybrid / Remote.
listingDate, listingDateDisplaystringExact posting timestamp, plus the site's relative label.
teaserstringThe short summary shown in search results.
searchContextobjectWhich keyword, location, page and rank produced this row.
jobDetails.job.contentstringThe complete job ad as HTML. Present when includeJobDetails is on.
jobDetails.job.products.questionnaireobjectThe employer's screening questions, when the ad has them.
jobDetails.job.products.bulletsarrayBenefit/perk bullets from the ad.
jobDetails.job.expiresAt, status, isExpiredWhether the role is still open and when it closes.
jobDetails.companySearchUrlstringLink 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" } }
}
}
FieldTypeDescription
totalCountintegerHow many matches the site reports for this search.
returnedCountintegerHow many jobs this run actually collected.
pagesFetchedintegerHow many result pages were read.
locationResolvedbooleanWhether your location was understood. Check this first if a search returns nothing — an unrecognised place name returns zero results rather than an error.
resolvedLocationobjectThe 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 raising maxItemsPerQuery.
  • totalCount is 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. returnedCount is 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 on jobId if 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. Setting salaryMin/salaryMax excludes them entirely.
  • Speed. Listing-only runs are fast (100 jobs per request). Turning on full descriptions adds one request per job — raise maxConcurrency for large runs, and lower it if the log starts showing rate limiting.
  • A proxy is optional. Residential is recommended for large or scheduled runs.
ActorWhat it does
agoda-reviews-scraperGuest reviews for any Agoda hotel
booking-reviews-scraperGuest reviews for any Booking.com property
tripcom-reviews-scraperGuest reviews for any Trip.com hotel
getyourguide-reviews-scraperTraveller reviews for GetYourGuide activities
viator-reviews-scraperTraveller reviews for Viator tours
holidaycheck-reviews-scraperGuest reviews for HolidayCheck hotels
priceline-reviews-scraperGuest reviews for Priceline hotels