# JobStreet Southeast Asia Job Search by Keyword & Country (`vexaloom-labs/jobstreet-southeast-asia-job-search-by-keyword`) Actor

Search JobStreet across Singapore, Malaysia, the Philippines, Indonesia and Thailand by keyword or country, with salary, job type and a direct apply link on every job.

- **URL**: https://apify.com/vexaloom-labs/jobstreet-southeast-asia-job-search-by-keyword.md
- **Developed by:** [vexaloom-labs](https://apify.com/vexaloom-labs) (community)
- **Categories:** Jobs, Automation, Lead generation
- **Stats:** 2 total users, 1 monthly users, 87.5% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.49 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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

## JobStreet & JobsDB Scraper: Jobs, Companies, Salaries

Scrape **JobStreet** and **JobsDB** across six Southeast Asian markets — Malaysia, Singapore, Indonesia, the Philippines, Thailand and Hong Kong. Get full job ads with parsed salary ranges and applicant demand, company profiles with employee reviews, and role salary benchmarks, all without a login.

### What this actor does

- **Five modes:** keyword search, scrape job / search / company URLs, company jobs, company profiles, and role salary benchmarks.
- **Full job ads:** description text or HTML, bullet points, screening questions, work type, work arrangement, classification, expiry date and apply link.
- **Structured salaries:** parsed minimum, maximum, currency and period from the posted salary label, plus a strict salary filter.
- **Applicant demand:** applicant count, application volume and resume / cover-letter percentages when the employer publishes them.
- **Company intelligence:** rating, review count, industry, size, website, perks, employee reviews, open jobs and salary ranges by role.
- **Incremental runs:** emit only new or changed jobs between scheduled runs, with NEW / UPDATED / REAPPEARED / EXPIRED change types.
- **Clean output:** fields the source does not show are omitted; `false` and `0` are kept.

### Services (modes)

| Mode | What it returns |
|---|---|
| `searchJobs` | Job records from one or more keywords and locations, with server-side category, work type, arrangement, date and sort filters plus strict client-side salary, keyword and applicant filters. |
| `byUrls` | Job records from job URLs, job records from search URLs, and company records from company URLs. Each URL's own market is used. |
| `companyJobs` | Open job records for one or more companies, found by company URL, numeric id or name. |
| `companyProfiles` | One company record per company, with optional reviews, salary ranges by role and current open jobs. |
| `salaryBenchmarks` | One record per role with typical monthly salary, growth, job satisfaction and classification, plus optional role details and state / city salary breakdowns. |

### How it works

The actor reads the same public listings the JobStreet and JobsDB sites show, using each market's own host, language and currency. Full job descriptions, company profiles, reviews and salary benchmarks come from the sites' public listing data rather than rendered pages, so results are consistent and fast. No account, cookie or proxy setup is required. Vietnam is not included because JobStreet Vietnam now redirects to Jora; Thailand is served by JobsDB at `th.jobsdb.com`.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `searchJobs` | One of the five modes above. |
| `keywords` | string | – | Job titles or keywords, one per line (mode=searchJobs). A small default search is used when empty. |
| `locations` | string | – | Cities or regions, one per line; combined with each keyword (mode=searchJobs). |
| `country` | string | `sg` | `my`, `sg`, `id`, `ph`, `th` or `hk`. |
| `classification` | string | – | Job category id (mode=searchJobs). |
| `subClassification` | string | – | Sub-category id; can be combined with classification (mode=searchJobs). |
| `workType` | string | – | `242` full time, `243` part time, `244` contract/temp, `245` casual/vacation. |
| `workArrangement` | string | – | `1` on-site, `2` hybrid, `3` remote. |
| `dateRange` | string | – | `1`, `3`, `7`, `14` or `31` days. |
| `listedAfter` | string | – | Keep jobs listed on or after `YYYY-MM-DD`. |
| `listedBefore` | string | – | Keep jobs listed on or before `YYYY-MM-DD`. |
| `salaryMin` | integer | – | Drop jobs whose salary is entirely below this amount. |
| `salaryMax` | integer | – | Drop jobs whose salary is entirely above this amount. |
| `salaryType` | string | `monthly` | `monthly`, `annual` or `hourly`; the unit for the salary bounds. |
| `sortBy` | string | `relevance` | `relevance` or `date`. |
| `startUrls` | string | – | Job, search or company URLs, one per line (mode=byUrls). |
| `companies` | string | – | Company URLs, numeric ids or names, one per line (mode=companyJobs / companyProfiles). |
| `includeDetails` | boolean | `true` | Fetch the full description, salary, applicant demand and company snapshot. |
| `descriptionFormat` | string | `text` | `text`, `html` or `both`. |
| `includeApplicantInsights` | boolean | `true` | Add applicant count, volume and resume / cover-letter percentages. |
| `includeCompanyProfile` | boolean | `true` | Add the company rating, industry, size, website and description to each job. |
| `includeReviews` | boolean | `false` | Fetch employee reviews (mode=companyProfiles). |
| `maxReviewsPerCompany` | integer | `10` | Review cap per company (1–100). |
| `includeCompanySalaries` | boolean | `false` | Fetch company salary ranges by role. |
| `includeOpenJobs` | boolean | `true` | Attach current open jobs (mode=companyProfiles). |
| `maxOpenJobs` | integer | `20` | Open-jobs cap per company (1–100). |
| `roles` | string | – | Role titles or queries to benchmark, one per line (mode=salaryBenchmarks). A default accounting role is used when empty. |
| `includeRegionalSalaries` | boolean | `false` | Add state and city salary breakdowns. |
| `includeRoleDetails` | boolean | `false` | Add role summary, tasks, skills, growth, review statistics and similar roles. |
| `includeKeywords` | string | – | Keep jobs whose title, company or description contains at least one term, one per line. |
| `excludeKeywords` | string | – | Drop jobs whose title, company or description contains any term, one per line. |
| `minApplicants` | integer | – | Drop jobs below this applicant count (requires details). |
| `maxApplicants` | integer | – | Drop jobs above this applicant count (requires details). |
| `language` | string | `en` | `en`, `id`, `th` or `zh`; used where the market supports it. |
| `compact` | boolean | `false` | Keep only core job fields for lightweight feeds. |
| `maxItems` | integer | `50` | Hard cap on records (1–5000). |
| `maxPages` | integer | `10` | Page cap per keyword/location (100 jobs per page). |
| `incrementalMode` | boolean | `false` | Emit only new or changed jobs (job modes). |
| `stateKey` | string | – | Name for saved incremental state; reuse it on each scheduled run. |
| `emitUnchanged` | boolean | `false` | Also emit jobs whose content has not changed. |
| `emitExpired` | boolean | `false` | Emit jobs that were seen before but have disappeared. |

### Output per job (`recordType="job"`)

Identity and links: `jobId`, `title`, `jobUrl`, `applyUrl`, `recordType`, `scrapedAt`.

Company: `company`, `companyId`, `companyUrl`, `companyLogoUrl`, `advertiserName`, `advertiserId`, `advertiserVerified`, `companyRating`, `companyReviewCount`, `companyIndustry`, `companySize`, `companyWebsite`, `companyDescription`, `companyPerks`.

Location: `location`, `locationCountry`, `locationCountryCode`, `locationState`, `locationRegion`, `locationSuburb`, `locationPostcode`, `country`.

Classification and work: `classification`, `classificationId`, `subClassification`, `subClassificationId`, `roleId`, `normalizedRoleTitle`, `jobType`, `workTypes`, `workArrangement`, `badges`.

Dates and content: `postedDate`, `listedAt`, `listedAtDisplay`, `expiresAt`, `isExpired`, `teaser`, `descriptionText`, `descriptionHtml`, `bulletPoints`, `screeningQuestions`.

Salary: `salary` (the posted label, only when it is a real salary), `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod`.

Demand and status: `applicantCount`, `applicantCountLabel`, `applicantVolumeLabel`, `resumePercentage`, `coverLetterPercentage`, `isLinkOut`, `isSponsored`, `adType`.

Incremental mode adds `changeType`, `firstSeenAt` and `lastSeenAt`.

### Output per company (`recordType="company"`)

`companyId`, `name`, `url`, `logoUrl`, `coverImageUrl`, `isClaimed`, `country`, `countryCode`, `industry`, `size`, `website`, `description`, `specialities`, `rating`, `reviewCount`, `recommendedPercent`, `ratingBreakdown`, `categoryRatings`, `perks`, `awards`, `aiSummary`, `reviewLocations`, `openJobsCount`, `openJobs`, `reviewTotal`, `reviews`, `salaryRanges`, `salaryUpdatedAt`, `recordType`, `scrapedAt`.

### Output per salary benchmark (`recordType="salaryBenchmark"`)

`roleId`, `alias`, `title`, `url`, `salaryMin`, `salaryMax`, `salaryMedian`, `salaryCurrency`, `salaryPeriod`, `growth`, `growthPercent`, `growthYears`, `jobSatisfaction`, `classifications`, `imageUrl`, `country`, `summary`, `tasksAndDuties`, `skills`, `reviewStats`, `similarRoles`, `locations`, `salaryLocation`, `recordType`, `scrapedAt`.

### Examples

#### Search accounting jobs in Kuala Lumpur

```json
{
  "mode": "searchJobs",
  "keywords": "accountant\nfinance executive",
  "locations": "Kuala Lumpur",
  "country": "my",
  "classification": "1200",
  "dateRange": "7",
  "salaryMin": 3000,
  "salaryMax": 6000,
  "salaryType": "monthly",
  "includeDetails": true,
  "maxItems": 100
}
```

#### Scrape pasted job and company URLs

```json
{
  "mode": "byUrls",
  "startUrls": "https://sg.jobstreet.com/job/95541255\nhttps://my.jobstreet.com/companies/mosca-168555693395725",
  "includeReviews": true,
  "maxReviewsPerCompany": 10,
  "maxItems": 20
}
```

#### Company profiles with reviews and open jobs

```json
{
  "mode": "companyProfiles",
  "companies": "Marina Bay Sands\nhttps://sg.jobstreet.com/companies/marina-bay-sands-168557908899025",
  "country": "sg",
  "includeReviews": true,
  "maxReviewsPerCompany": 30,
  "includeCompanySalaries": true,
  "includeOpenJobs": true,
  "maxOpenJobs": 25
}
```

#### Role salary benchmarks with regional detail

```json
{
  "mode": "salaryBenchmarks",
  "roles": "data analyst\naccountant",
  "country": "my",
  "includeRoleDetails": true,
  "includeRegionalSalaries": true,
  "maxItems": 10
}
```

### Use cases

- **Recruitment market research:** compare demand, salaries and work arrangements across six Southeast Asian markets.
- **Compensation benchmarking:** collect posted salary ranges and official role salary guides in local currencies.
- **Job feed aggregation:** power a regional job board with full descriptions, expiry dates and apply links.
- **Talent sourcing:** find companies hiring for a role and pull their profile, reviews and open jobs.
- **Competitive intelligence:** track which employers are hiring, how often roles are refreshed and what they pay.
- **AI and MCP pipelines:** use compact output for lightweight, structured job feeds.

### Usage cost

The actor does not add a separate per-item fee of its own; you pay for the Apify platform compute your run uses. A search run with full details costs roughly one listing request plus one detail request per returned job, so `maxItems` is the main cost control. A small scheduled run with 3–50 jobs is inexpensive; large runs with thousands of jobs and company reviews cost more. Use `compact` and `includeDetails=false` for high-volume monitoring.

### FAQ

**Which countries are covered?**
Malaysia, Singapore, Indonesia, the Philippines (JobStreet) plus Thailand and Hong Kong (JobsDB). Vietnam is no longer a JobStreet market and redirects to Jora, so it is not offered.

**Do I need a JobStreet account or cookies?**
No. The actor reads public listings and public company data without a login, cookie or proxy.

**Why is salary missing on some jobs?**
Many employers do not publish a salary. When the posted label contains no real salary — for example "Weekends Off, Remote" — the salary fields are omitted rather than guessed.

**How does the salary filter work when the site's own filter is inexact?**
The actor parses each job's salary and keeps only jobs whose advertised range overlaps your minimum and maximum. Jobs without a published salary are excluded when a salary bound is set. Salary values are converted between monthly, annual and hourly for the comparison.

**Can one run search several markets?**
Each run uses one `country`, or the market of each URL in `byUrls`. Run once per market if you need a combined dataset.

**How complete are company reviews and salary ranges?**
They are returned when the employer has claimed a company profile and has published reviews or salary data. Jobs without a profile still return the job fields; the company enrichment is simply omitted.

**What is the difference between `companyJobs` and `companyProfiles`?**
`companyJobs` returns individual open jobs for the companies you supply. `companyProfiles` returns one record per company with optional reviews, salary ranges and a list of open jobs.

**How does incremental mode decide a job changed?**
It compares title, company, location, salary, description, applicant count and expiry between runs. New jobs are `NEW`, changed jobs `UPDATED`, returning jobs `REAPPEARED`, and disappeared jobs `EXPIRED` when enabled. Around 50,000 job ids are remembered per state key.

**Is this affiliated with JobStreet or JobsDB?**
No. This actor reads public listings and is not affiliated with, endorsed by, or sponsored by JobStreet, JobsDB or SEEK.

### Notes

- Empty fields are omitted at every level; `false` and `0` are preserved.
- Dates are ISO 8601 in UTC; `postedDate` is a `YYYY-MM-DD` date.
- Salary amounts are emitted in the market's currency unless the label names another currency.
- Company URLs and job URLs always point at the canonical market host.
- Private-advertiser jobs keep the site's "Private Advertiser" company label; company profile fields are omitted when no profile exists.
- `byUrls` accepts job links, search links and company links, including legacy JobStreet and JobsDB domains; a page number in a search link is honoured.
- A company list with several companies is interleaved, so `maxItems` covers every company instead of stopping at the first one.
- The default daily run is one small Singapore search with three jobs and full details.

### Limitations

- **Company coverage is conditional.** Not every employer has a claimed profile, rating, reviews or salary ranges. Fields are omitted when absent.
- **Salary labels vary.** The parser handles ranges, single figures, `k`, "Up to", monthly/annual/hourly periods, and Malaysian, Singaporean, Indonesian, Philippine, Thai and Hong Kong formats. Unusual or malformed labels may be omitted.
- **Search results change constantly.** The same query can return a different order or new jobs between runs; use incremental mode and a stable `stateKey` for scheduled monitoring.
- **Listing depth follows the site's own result count.** Pages are 100 jobs each and stop at the source's total; very broad queries can return many pages.
- **No HTML fallback.** The actor relies on the public listing data the sites expose; if a market changes that data, the affected fields are omitted and the run status reports the failure.
- **No built-in notifications.** Use Apify schedules and integrations to act on new or changed jobs.
- **Review data is employer-published.** Reviews can be old, sparse or absent for smaller companies.

# Actor input Schema

## `mode` (type: `string`):

What to fetch from JobStreet / JobsDB.

## `keywords` (type: `string`):

One job title or keyword per line (mode=searchJobs). Each keyword is searched separately and results are deduplicated.

## `locations` (type: `string`):

Optional cities or regions, one per line; combined with each keyword (mode=searchJobs).

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

Market to search. Covers JobStreet Malaysia, Singapore, Indonesia and the Philippines, plus JobsDB Thailand and Hong Kong.

## `classification` (type: `string`):

Optional job category filter (mode=searchJobs).

## `subClassification` (type: `string`):

Optional sub-category filter; can be combined with a classification (mode=searchJobs).

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

Employment type filter (mode=searchJobs).

## `workArrangement` (type: `string`):

On-site, hybrid or remote (mode=searchJobs).

## `dateRange` (type: `string`):

Only jobs listed in the last N days (mode=searchJobs).

## `listedAfter` (type: `string`):

Drop jobs listed before this date (YYYY-MM-DD).

## `listedBefore` (type: `string`):

Drop jobs listed after this date (YYYY-MM-DD).

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

Drop jobs whose advertised salary is entirely below this amount, in the unit chosen by Salary type. Jobs with no salary are dropped when this is set.

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

Drop jobs whose advertised salary is entirely above this amount, in the unit chosen by Salary type.

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

Unit for the salary minimum / maximum filters.

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

Result order (mode=searchJobs).

## `startUrls` (type: `string`):

Job, search or company URLs, one per line (mode=byUrls). Each URL's own market is used; a search URL keeps its page number.

## `companies` (type: `string`):

Company URLs, profile or organisation ids, or names, one per line (mode=companyJobs / companyProfiles). Several companies are interleaved so maxItems covers each one.

## `includeDetails` (type: `boolean`):

Fetch the full description, salary, applicant demand and company snapshot for each job (job modes).

## `descriptionFormat` (type: `string`):

How job descriptions are returned.

## `includeApplicantInsights` (type: `boolean`):

Add applicant count, application volume and resume / cover-letter percentages when the source exposes them.

## `includeCompanyProfile` (type: `boolean`):

Add company rating, industry, size, website and description to each job when available.

## `includeReviews` (type: `boolean`):

Fetch employee reviews for each company (mode=companyProfiles, or company URLs in byUrls).

## `maxReviewsPerCompany` (type: `integer`):

Review cap per company.

## `includeCompanySalaries` (type: `boolean`):

Fetch salary ranges by role for each company.

## `includeOpenJobs` (type: `boolean`):

Attach the company's current open jobs (mode=companyProfiles).

## `maxOpenJobs` (type: `integer`):

Cap on attached open jobs per company.

## `roles` (type: `string`):

Role titles or queries to benchmark, one per line (mode=salaryBenchmarks).

## `includeRegionalSalaries` (type: `boolean`):

Add state / city salary breakdowns for each role.

## `includeRoleDetails` (type: `boolean`):

Add role summary, tasks, skills, growth, review statistics and similar roles.

## `includeKeywords` (type: `string`):

Keep only jobs whose title, company or description contains at least one term, one per line (case-insensitive).

## `excludeKeywords` (type: `string`):

Drop jobs whose title, company or description contains any term, one per line.

## `minApplicants` (type: `integer`):

Drop jobs with fewer applicants than this. Requires job details.

## `maxApplicants` (type: `integer`):

Drop jobs with more applicants than this. Requires job details.

## `language` (type: `string`):

Interface language. Only English is available in every market; other options are used where the market supports them.

## `compact` (type: `boolean`):

Keep only core job fields (identity, company, salary, dates, URL) for lightweight feeds.

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

Hard cap on records returned. Applies across all keywords, locations and pages.

## `maxPages` (type: `integer`):

Page cap for each keyword/location (100 jobs per page).

## `incrementalMode` (type: `boolean`):

Emit only new or changed jobs, using saved state between runs (job modes).

## `stateKey` (type: `string`):

Name for the saved incremental state. Use the same key on each scheduled run.

## `emitUnchanged` (type: `boolean`):

When incremental mode is on, also emit jobs whose content has not changed.

## `emitExpired` (type: `boolean`):

When incremental mode is on, emit jobs that were seen before but have disappeared.

## Actor input object example

```json
{
  "mode": "searchJobs",
  "country": "sg",
  "salaryType": "monthly",
  "sortBy": "relevance",
  "includeDetails": true,
  "descriptionFormat": "text",
  "includeApplicantInsights": true,
  "includeCompanyProfile": true,
  "includeReviews": false,
  "maxReviewsPerCompany": 10,
  "includeCompanySalaries": false,
  "includeOpenJobs": true,
  "maxOpenJobs": 20,
  "includeRegionalSalaries": false,
  "includeRoleDetails": false,
  "language": "en",
  "compact": false,
  "maxItems": 3,
  "maxPages": 1,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false
}
```

# Actor output Schema

## `jobs` (type: `string`):

Dataset containing job, company and salary benchmark records.

# 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 = {
    "mode": "searchJobs",
    "country": "sg",
    "salaryType": "monthly",
    "sortBy": "relevance",
    "includeDetails": true,
    "descriptionFormat": "text",
    "includeApplicantInsights": true,
    "includeCompanyProfile": true,
    "includeReviews": false,
    "maxReviewsPerCompany": 10,
    "includeCompanySalaries": false,
    "includeOpenJobs": true,
    "maxOpenJobs": 20,
    "includeRegionalSalaries": false,
    "includeRoleDetails": false,
    "language": "en",
    "compact": false,
    "maxItems": 3,
    "maxPages": 1,
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("vexaloom-labs/jobstreet-southeast-asia-job-search-by-keyword").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 = {
    "mode": "searchJobs",
    "country": "sg",
    "salaryType": "monthly",
    "sortBy": "relevance",
    "includeDetails": True,
    "descriptionFormat": "text",
    "includeApplicantInsights": True,
    "includeCompanyProfile": True,
    "includeReviews": False,
    "maxReviewsPerCompany": 10,
    "includeCompanySalaries": False,
    "includeOpenJobs": True,
    "maxOpenJobs": 20,
    "includeRegionalSalaries": False,
    "includeRoleDetails": False,
    "language": "en",
    "compact": False,
    "maxItems": 3,
    "maxPages": 1,
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
}

# Run the Actor and wait for it to finish
run = client.actor("vexaloom-labs/jobstreet-southeast-asia-job-search-by-keyword").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 '{
  "mode": "searchJobs",
  "country": "sg",
  "salaryType": "monthly",
  "sortBy": "relevance",
  "includeDetails": true,
  "descriptionFormat": "text",
  "includeApplicantInsights": true,
  "includeCompanyProfile": true,
  "includeReviews": false,
  "maxReviewsPerCompany": 10,
  "includeCompanySalaries": false,
  "includeOpenJobs": true,
  "maxOpenJobs": 20,
  "includeRegionalSalaries": false,
  "includeRoleDetails": false,
  "language": "en",
  "compact": false,
  "maxItems": 3,
  "maxPages": 1,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false
}' |
apify call vexaloom-labs/jobstreet-southeast-asia-job-search-by-keyword --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,vexaloom-labs/jobstreet-southeast-asia-job-search-by-keyword"
        }
    }
}
```

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/ICtD36jdoiLMMlH3a/builds/zMLcGwfJFPYiCPd46/openapi.json
