# JobStreet Jobs Scraper (`lergassy/jobstreet-jobs-scraper`) Actor

Scrape JobStreet and JobsDB job ads across Malaysia, Singapore, Indonesia, the Philippines, Thailand and Hong Kong by keyword and location: title, company, salary with parsed numbers, work type, industry, date, teaser, optional full advert. Sort, filter, export to JSON/CSV, no login.

- **URL**: https://apify.com/lergassy/jobstreet-jobs-scraper.md
- **Developed by:** [Matvey](https://apify.com/lergassy) (community)
- **Categories:** Jobs, Lead generation, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 1,000 jobs

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

Scrape job listings from **JobStreet (Malaysia, Singapore, Indonesia, Philippines) and JobsDB (Thailand, Hong Kong)** — the public search API the site itself uses, no login, no browser. One flat row per job: title, company, location, salary (text and parsed numbers), work type, industry, listing date, teaser and highlights. Turn on **Full advert text** to add the complete description, expiry date and company profile.

### What data can it extract

| Field | Example |
|---|---|
| `title`, `companyName`, `companyUrl` | Registered Nurse · BaptistCare NSW & ACT · …/companies/baptistcare-… |
| `location`, `locationHierarchy`, `workArrangement` | Baulkham Hills, Sydney NSW · \["Baulkham Hills NSW 2153", "All Sydney NSW"] · On-site |
| `salary`, `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod` | $48 – $52 per hour · 48 · 52 · AUD · hour |
| `workType`, `classification`, `subclassification` | Full time · Healthcare & Medical · Nursing - Aged Care |
| `listedAt`, `listedAgo`, `isFeatured`, `tags` | 2026-09-24T01:20:01Z · 23h ago · true · \["Be an early applicant"] |
| `teaser`, `bulletPoints` | short summary · \["Join a Purpose-Driven Team", …] |
| `description`, `descriptionHtml`, `expiresAt`, `isExpired` | full advert (add-on) |

Measured on 25 Sep 2026: "accountant" in Singapore lists 4,361 jobs, "nurse" in Malaysia 1,004, in the Philippines 1,597, in Indonesia 689, in Hong Kong 389. Search results come 100 per request; the full advert is one extra request per job.

### How much does it cost

**$1.00 per 1,000 jobs** (FREE plan; $0.60 on Diamond). Full advert text is an add-on at **$0.50 per 1,000**. Nothing per run, per search or per page; rows that fail are free. The free Apify plan ($5 credit) covers about 5,000 jobs.

#### Bulk export: what 50,000 jobs actually cost (25 Sep 2026)

| Actor | Per job | Per run | 50,000 jobs, 100 runs |
|---|---|---|---|
| **JobStreet Jobs Scraper (this one)** | $0.001 | $0 | **$50** (+$25 with full adverts) |
| blackfalcondata/jobstreet-scraper (most used) | $0.002 | $0.01 | $101 |
| shahidirfan/JobStreet-Scraper | $0.00099 | $0.0005 | $49.55 |
| memo23/jobstreet-scraper | $0.0009 | $0.005 | $45.50 |

Prices are FREE-plan prices from each Actor's page on the date above; Actors that ask less per row exist, they are listed where that is the case.

### How to scrape JobStreet jobs

1. Type keywords (`registered nurse`, `data analyst`) and a location. Pick the country site.
2. Optional: sort by date, limit to the last 7 days, filter by work type or salary. Turn on **Full advert text** if you need descriptions.
3. Run and download JSON, CSV or Excel, or read the dataset through the API.

#### Input

```json
{ "keywords": ["registered nurse"], "location": "Sydney NSW", "country": "AU", "maxJobsPerSearch": 500, "postedWithinDays": 7, "includeDescription": true }
```

#### Output

```json
{ "type": "job", "id": "94844376", "title": "Residential Manager", "url": "https://www.seek.com.au/job/94844376", "site": "SEEK", "country": "AU",
  "companyName": "BaptistCare NSW & ACT", "location": "Baulkham Hills, Sydney NSW", "salary": "$48 – $52 per hour", "salaryMin": 48, "salaryMax": 52, "salaryCurrency": "AUD", "salaryPeriod": "hour",
  "workType": "Contract/Temp", "workArrangement": "On-site", "classification": "Healthcare & Medical", "subclassification": "Nursing - Aged Care",
  "listedAt": "2026-09-24T01:20:01Z", "teaser": "Lead with clinical expertise…", "bulletPoints": ["Join a Purpose-Driven Team", "Lead with compassion, serve with purpose"],
  "description": "Lead with clarity, purpose and heart — …", "expiresAt": "2026-10-24T12:59:59.999Z" }
```

### Use cases

#### Recruitment agencies

Daily feed of new adverts in your specialty and city; `id` is stable, so scheduled runs add only new jobs.

#### Salary research and HR analytics

`salaryMin`/`salaryMax`/`salaryPeriod` are parsed numbers — median pay by role, city and industry in one pivot.

#### Job boards and aggregators

Bulk export by keyword × location on a schedule at $1 per 1,000 rows.

#### AI agents

Call it through the Apify MCP server or x402 with a plain request ("part-time nursing jobs in Brisbane listed this week") and get structured rows.

### Integrations

Apify API and clients (Python, JavaScript), n8n, Make, Zapier, Google Sheets, webhooks, Apify MCP server. Schedule it in the Console for a live feed.

```bash
curl -X POST "https://api.apify.com/v2/acts/lergassy~jobstreet-jobs-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" -d '{"keywords":["accountant"],"maxJobsPerSearch":200,"sortBy":"date"}'
```

### Limits and troubleshooting

- Work type and salary filters are applied by the site itself and are as loose as on the website (a "full time" search can include part-time adverts that match).
- The site returns at most a few thousand results per search; split by location or industry to go deeper.
- Advertiser phone numbers are not published on the site and are not collected.

### ❓ FAQ

#### Is it legal to scrape JobStreet?

The Actor reads public job adverts that the site shows to any visitor and collects no personal data. Use the data in line with the site's terms and your local law.

#### How fresh is the data?

Live at run time. Schedule the Actor hourly or daily.

#### Does it work without the full advert?

Yes — search rows already include title, company, location, salary, type, industry, date and teaser. Turn the add-on on only when you need the description.

### Your feedback

If a field is missing or something stops working, open an issue on the Actor page — fixes usually ship the same day. A ⭐ review helps other people find the Actor.

### You might also like

| Actor | What it does |
|---|---|
| [SEEK Jobs Scraper](https://apify.com/lergassy/seek-jobs-scraper) | SEEK — Australia and New Zealand |
| [Jobs API](https://apify.com/lergassy/jobs-api) | Indeed, LinkedIn and ATS boards in one run |
| [Indeed Jobs Scraper](https://apify.com/lergassy/indeed-jobs-scraper) | Indeed by keyword and location |
| [Workday Jobs Scraper](https://apify.com/lergassy/workday-jobs-scraper) | Any company career site on Workday |

# Actor input Schema

## `keywords` (type: `array`):

Job titles or skills, one search each: <b>registered nurse</b>, <b>data analyst</b>, <b>forklift</b>. Leave empty to list every job in the location.

## `location` (type: `string`):

City or state as the site writes it: <b>Kuala Lumpur</b>, <b>Selangor</b>, <b>Jakarta Raya</b>, <b>Cebu</b>. Empty = whole country.

## `country` (type: `string`):

Which site to search.

## `maxJobsPerSearch` (type: `integer`):

Stop each keyword search after this many jobs (100 per page, up to the site's own limit of a few thousand per search).

## `sortBy` (type: `string`):

Newest first or the site's relevance ranking.

## `postedWithinDays` (type: `integer`):

0 = any time. The site accepts 1, 3, 7, 14 or 31.

## `workType` (type: `string`):

Filter by employment type.

## `salaryMin` (type: `integer`):

Lower salary bound in local currency, per the salary type below.

## `salaryMax` (type: `integer`):

Upper salary bound.

## `salaryType` (type: `string`):

Period the salary bounds refer to.

## `includeDescription` (type: `boolean`):

Fetch the full description, expiry date and company profile for every job — one extra request per job, add-on $0.50 per 1,000.

## `jobUrls` (type: `array`):

Individual job pages to fetch in full, e.g. https://www.seek.com.au/job/94844376.

## `maxItems` (type: `integer`):

Hard stop for the whole run.

## `proxyConfiguration` (type: `object`):

Apify datacenter proxy is on by default so a schedule does not hammer the site from one address. Residential is not needed.

## Actor input object example

```json
{
  "keywords": [
    "accountant"
  ],
  "country": "MY",
  "maxJobsPerSearch": 50,
  "sortBy": "relevance",
  "postedWithinDays": 0,
  "workType": "",
  "salaryType": "annual",
  "includeDescription": false,
  "maxItems": 100000,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `rows` (type: `string`):

One row per JobStreet / JobsDB job ad.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "keywords": [
        "accountant"
    ],
    "location": "",
    "maxJobsPerSearch": 50,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("lergassy/jobstreet-jobs-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "keywords": ["accountant"],
    "location": "",
    "maxJobsPerSearch": 50,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("lergassy/jobstreet-jobs-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "keywords": [
    "accountant"
  ],
  "location": "",
  "maxJobsPerSearch": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call lergassy/jobstreet-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lergassy/jobstreet-jobs-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/npl5CpAdN8LwvQUxI/builds/UTitGemgqqMqGDgFM/openapi.json
