# JobStreet Job Listings Scraper (`fetch_cat/jobstreet-job-listings-scraper`) Actor

Export public JobStreet job listings by keyword, country, and optional location into structured records for recruitment research and market analysis.

- **URL**: https://apify.com/fetch\_cat/jobstreet-job-listings-scraper.md
- **Developed by:** [Hanna Nosova](https://apify.com/fetch_cat) (community)
- **Categories:** Jobs, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.60 / 1,000 item processeds

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## JobStreet Job Listings Scraper

Export public JobStreet job listings from supported Southeast Asian JobStreet marketplaces. Search by keyword, choose a marketplace, and download structured records for recruitment research, salary analysis, and hiring-market monitoring.

### Input recipes

```json
{
  "query": "software engineer",
  "country": "ID",
  "maxItems": 25
}
```

| Input | Description |
| --- | --- |
| `query` | Job title or keywords to search. |
| `country` | Marketplace: `MY`, `SG`, `ID`, or `PH`. |
| `location` | Optional location refinement. |
| `maxItems` | Number of listings to export (1–100). |

### What you get

Each result represents one public JobStreet listing. Search results currently provide title, employer, location, salary label, classification, work type, teaser text, dates, and source context. Fields unavailable in the public search response are returned as `null` or an empty list rather than guessed.

```json
{
  "jobId": "94228905",
  "title": "Software Engineer Project Manager",
  "company": "HiThink Technology Indonesia",
  "location": "South Jakarta, Jakarta",
  "salaryText": "Rp 13.500.000 – Rp 20.000.000 per month",
  "salaryCurrency": "IDR",
  "canonicalUrl": "https://id.jobstreet.com/job/94228905"
}
```

#### Output fields

| Group | Fields |
| --- | --- |
| Identity and employer | `jobId`, `seekJobId`, `title`, `canonicalUrl`, `company`, `companyUrl`, `advertiserId` |
| Location and salary | `location`, `locationCountry`, `locationState`, `locationSuburb`, `locationPostcode`, `salaryText`, `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryType` |
| Job classification | `employmentType`, `workArrangement`, `category`, `subCategory`, `roleId`, `teaser`, `bulletPoints` |
| Description and company details | `description`, `descriptionHtml`, `descriptionMarkdown`, `descriptionLength`, `contentQuality`, `companyIndustry`, `companySize`, `companyWebsite`, `phoneNumber`, `screeningQuestions`, `applyUrl` |
| Dates and source | `postedDate`, `validThrough`, `contentHash`, `isSponsored`, `sourceUrl`, `sourceCountry`, `sourceDomain`, `searchQuery`, `searchUrl`, `scrapedAt`, `fetchedAt`, `detailFetched`, `extractedEmails` |
| Tracking compatibility | `changeType`, `trackedHash`, `firstSeenAt`, `lastSeenAt`, `previousSeenAt`, `expiredAt`, `stateKey`, `isRepost`, `repostOfId`, `repostDetectedAt` |

### Pricing and limits

The Actor charges a small start fee and per exported listing. See the [live Pricing tab](https://apify.com/fetch_cat/jobstreet-job-listings-scraper/pricing) for current tiered rates. Each run returns 1–100 listings; source availability and disclosed fields vary by listing.

### Who is it for?

- **Recruiters and talent teams** building role- and location-specific prospecting lists.
- **Market researchers** comparing public hiring demand, employers, and disclosed compensation.
- **Analysts and developers** feeding structured JobStreet records into dashboards, databases, or agents.
- **Job-market monitors** tracking public listings repeatedly through stable job IDs and source URLs.

### Use cases

- Build a list of relevant openings for recruitment research.
- Compare advertised salary ranges across locations and job categories.
- Monitor public hiring demand for a keyword or role.

### Limits

Results reflect the fields publicly returned by JobStreet at request time. Salary and employer details vary by listing. The actor does not access login-only data and never fabricates unavailable detail fields.

### Tips for useful searches

- Use role-focused terms such as `software engineer`, `accountant`, or `customer service`.
- Start with 10–25 listings to review a new query, then raise `maxItems` when it returns relevant roles.
- Select the country where the hiring market is relevant; results are not inferred from your location.
- Keep `salaryText` alongside normalized salary values because listings may use different pay periods or disclose no pay.
- Save `jobId`, `canonicalUrl`, and `scrapedAt` when comparing repeated exports over time.

### Working with the data

| Goal | Suggested fields |
| --- | --- |
| Find new openings | `title`, `company`, `location`, `postedDate`, `canonicalUrl` |
| Compare compensation | `salaryText`, `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryType` |
| Segment hiring demand | `category`, `subCategory`, `employmentType`, `workArrangement` |
| Keep a research trail | `jobId`, `sourceUrl`, `searchQuery`, `scrapedAt`, `contentHash` |

### FAQ

**Which marketplaces are supported?** Malaysia, Singapore, Indonesia, and the Philippines.

**Why are some fields empty?** JobStreet does not disclose every salary, employer, or listing-detail field in every public search response.

**Can I use this in an agent workflow?** Yes. Submit the same JSON input through the Apify API or the Actor's MCP integration.

**Does it access private job data?** No. It exports only public listing data available at request time.

### Related Actors

- [Google Jobs Scraper](https://apify.com/fetch_cat/google-jobs-scraper)
- [Indeed Jobs Scraper](https://apify.com/fetch_cat/indeed-jobs-scraper)
- [LinkedIn Jobs Scraper](https://apify.com/fetch_cat/linkedin-jobs-scraper)
- [Career Page Job Postings Scraper](https://apify.com/fetch_cat/career-page-job-postings-scraper)
- [Remote.com Jobs Scraper](https://apify.com/fetch_cat/remote-dot-com-jobs-scraper)

### API usage

#### Node.js

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('fetch_cat/jobstreet-job-listings-scraper').call({
  query: 'software engineer', country: 'ID', maxItems: 25,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python

```python
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("fetch_cat/jobstreet-job-listings-scraper").call(
    run_input={"query": "software engineer", "country": "ID", "maxItems": 25}
)
print(list(client.dataset(run["defaultDatasetId"]).iterate_items()))
```

#### cURL

```bash
curl -X POST 'https://api.apify.com/v2/acts/fetch_cat~jobstreet-job-listings-scraper/runs?token=YOUR_APIFY_TOKEN' \
  -H 'content-type: application/json' \
  -d '{"query":"software engineer","country":"ID","maxItems":25}'
```

### MCP and agent workflows

Use the same structured input with the [Apify MCP server](https://mcp.apify.com?tools=fetch_cat/jobstreet-job-listings-scraper). Add it to Claude Code with:

```bash
claude mcp add --transport http apify https://mcp.apify.com?tools=fetch_cat/jobstreet-job-listings-scraper
```

Or add this server configuration to an MCP-compatible client:

```json
{
  "mcpServers": {
    "apify": {
      "type": "http",
      "url": "https://mcp.apify.com?tools=fetch_cat/jobstreet-job-listings-scraper"
    }
  }
}
```

Example prompts:

- "Find 20 public software engineer openings on JobStreet Malaysia and summarize the employers and locations."
- "Export public accounting jobs in Singapore and group listings by disclosed salary range."
- "Compare titles, work arrangements, and employers in this JobStreet result dataset."

An agent can run a country-specific search, then filter the returned default-dataset rows by title, location, employer, or disclosed salary.

### Examples

The Actor currently provides **Input recipes** above. After publication, Publisher will add verified, ready-to-run examples for Indonesia software-engineering and Malaysia accounting searches; this README will then link only to real public example pages.

### Support

If a supported marketplace returns no listings for a known public query, include the input and run URL when contacting support so the route can be checked.

# Actor input Schema

## `query` (type: `string`):

Terms to search for on JobStreet.

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

Marketplace to search.

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

Optional public JobStreet location refinement.

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

Maximum listings to export.

## Actor input object example

```json
{
  "query": "software engineer",
  "country": "MY",
  "maxItems": 10
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

# 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 = {
    "query": "software engineer"
};

// Run the Actor and wait for it to finish
const run = await client.actor("fetch_cat/jobstreet-job-listings-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 = { "query": "software engineer" }

# Run the Actor and wait for it to finish
run = client.actor("fetch_cat/jobstreet-job-listings-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 '{
  "query": "software engineer"
}' |
apify call fetch_cat/jobstreet-job-listings-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,fetch_cat/jobstreet-job-listings-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/xeSOXpmhYvLhs0ckg/builds/pPrHya7gAD33oLZMB/openapi.json
