# PTgoodjobs (CTgoodjobs) Scraper - HK Frontline & Part-Time Jobs (`youfuxu/ptgoodjobs-hongkong-jobs-scraper`) Actor

Scrape Hong Kong frontline jobs from PTgoodjobs (pt.ctgoodjobs.hk), CTgoodjobs' channel for retail, F\&B, healthcare, clerical, logistics and driver roles, full-time and part-time: titles, companies, districts, HKD salaries, employment type, descriptions. Main CTgoodjobs board not included.

- **URL**: https://apify.com/youfuxu/ptgoodjobs-hongkong-jobs-scraper.md
- **Developed by:** [Youfu Xu](https://apify.com/youfuxu) (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 $3.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## PTgoodjobs (by CTgoodjobs) Scraper — Hong Kong frontline & part-time jobs

Get clean, structured job data from **[PTgoodjobs](https://pt.ctgoodjobs.hk)** (搵工快) — the frontline-hiring channel run by **CTgoodjobs**, one of Hong Kong's largest recruitment sites. PTgoodjobs carries **2,500+ live full-time and part-time openings** in retail, F\&B and hotels, property management and security, healthcare and elderly care, clerical and customer service, logistics, warehousing and driving, beauty, education and tutoring. Search any keyword in English or Chinese, filter by Hong Kong district and employment type, and download the results as JSON, CSV or Excel. No login, no browser, no proxy.

> **Scope note:** this Actor reads `pt.ctgoodjobs.hk` only. It does **not** cover the main CTgoodjobs white-collar job board (`jobs.ctgoodjobs.hk`), which sits behind a human-verification wall. If you need banking, IT or management roles from the main board, this is not the right tool.

### What you get

Run it with `includeDetails: true` and a job looks like this:

```json
{
  "url": "https://pt.ctgoodjobs.hk/job/60406256/%e7%8f%a0%e5%af%b6%e5%ba%97%e8%b3%ac%e6%88%bf-jewellery-cashier",
  "jobId": "60406256",
  "title": "珠寶店賬房 Jewellery Cashier",
  "companyName": "Chong Fai Group Holdings Company Limited",
  "companyUrl": "https://pt.ctgoodjobs.hk/company-jobs/chong-fai-group-holdings-company-limited/00084833",
  "companyLogoUrl": "https://res03.ctgoodjobs.hk/images/company_profile/comp_d.gif",
  "location": "Kowloon > Others",
  "salaryText": "15,000 - 20,000 / month",
  "salaryMin": 15000,
  "salaryMax": 20000,
  "salaryCurrency": "HKD",
  "salaryPeriod": "month",
  "employmentType": "Full-time",
  "benefits": [],
  "postedText": "Posted on 30d+ ago",
  "postedAt": "2026-07-14T00:00:00+08:00",
  "deadline": "2026-08-28T23:59:59+08:00",
  "description": "為配合業務擴充及發展，本公司現招聘珠寶店賬房數名\n\n賬房工作職責：\n一般收銀員工作；結帳及操作收銀機；協助店舖日常運作\n\n入職要求\n工作積極主動、待客有熱誠、有禮…",
  "descriptionHtml": "<p>為配合業務擴充及發展，本公司現招聘珠寶店賬房數名</p><p>賬房工作職責：</p><ul><li><p>一般收銀員工作…",
  "jobFunctions": ["Retail - Watch · Accessories · Electronics · Others"],
  "locations": ["Kowloon > Others"],
  "employmentTerms": ["Full-time"],
  "employmentTypeSchema": ["FULL_TIME"],
  "education": [],
  "benefitsDetail": [],
  "contactNo": "",
  "contactPerson": "",
  "workPermit": "Only accept candidates with permission working in Hong Kong",
  "language": "en",
  "scrapedAt": "2026-08-21T07:13:58.430Z"
}
```

**18 fields per job straight from the search results** — title, company, company page and logo, district, salary text plus parsed `salaryMin` / `salaryMax` / `salaryCurrency` / `salaryPeriod`, employment type, benefit tags, posting age and an ISO `postedAt`.

Turn on **Include detail page data** and each job gains **12 more**: the full description as text and HTML, exact posted date and application `deadline`, job functions, every district the job covers, all employment terms (e.g. Full-time + Permanent + Contract), education requirements, the employer's benefits list, contact number / contact person when the employer publishes one, and the work-permit note.

Salaries are parsed from formats like `16,000 - 18,000 / month`, `65 - 70 / hour` and `70 above / hour` into numbers. Jobs that say `negotiable` or `N/A` come back with `null` salary numbers rather than a misleading `0` — in frontline hiring that is the majority of listings, so always keep `salaryText` alongside the numbers.

### Who uses this

- **Staffing agencies & HR teams** — see which retailers, restaurants, hotels, property managers and care homes are hiring right now, in which districts, at what hourly or monthly pay
- **Wage benchmarking** — hourly rates for cashiers, waiters, cleaners, security guards and promoters, by district, refreshed whenever you run it
- **Lead generation** — every row names the hiring company with a link to its PTgoodjobs page and logo; frontline employers hiring now are warm leads for staffing, payroll, uniform, POS and training vendors
- **Job aggregators & alert bots** — poll a keyword or district daily and diff against yesterday's dataset to catch new postings
- **Labour-market research** — measure hiring volume for part-time vs full-time roles across Hong Kong Island, Kowloon, the New Territories and the Outlying Islands

### How to use

1. Enter a **keyword** — `sales`, `cashier`, `waiter`, `security`, `nurse`, `driver`, `收銀`, `文員`, `保安` all work (2 characters minimum)
2. Optionally set a **district filter**: comma-separated names as the site spells them, e.g. `Mongkok, Tsimshatsui`, `Tsuen Wan`, `旺角`, or a whole region with `1_r` (Hong Kong Island), `2_r` (Kowloon), `3_r` (New Territories), `4_r` (Outlying Islands)
3. Optionally pick **employment types**: full-time, part-time, permanent, temporary, contract, internship, freelance
4. Choose the **data language**: `en` gives English district names, salary units and labels; `zh` gives Traditional Chinese. Job titles and descriptions stay in whatever language the employer wrote
5. Set **Max jobs** (default 50; the site pages 16 at a time) and optionally enable **Include detail page data**
6. Run, then download from the **Dataset** tab as JSON / CSV / Excel, or pull it through the Apify API

#### Example input

```json
{
  "keyword": "waiter",
  "location": "Causeway Bay, Wanchai, Tsimshatsui",
  "employmentType": ["part-time"],
  "language": "en",
  "maxItems": 200,
  "includeDetails": true
}
```

### Output fields

| Field | Description |
| --- | --- |
| `url` | Job detail page on pt.ctgoodjobs.hk |
| `jobId` | PTgoodjobs job ID |
| `title` | Job title as posted (often bilingual) |
| `companyName`, `companyUrl`, `companyLogoUrl` | Hiring company, its PTgoodjobs company page and logo |
| `location` | Primary district, e.g. `Mongkok`, `HK International Airport`, `Kowloon (Multiple locations)` |
| `salaryText` | Salary exactly as shown, e.g. `65 - 70 / hour`, `negotiable` |
| `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod` | Parsed numbers in HKD with `month` / `hour` / `day` / `year`; `null` / empty when not disclosed |
| `employmentType` | `Full-time`, `Part-time` or both |
| `benefits` | Benefit tags shown on the result card, e.g. `Bonus` |
| `postedText`, `postedAt` | Posting age as displayed and as an ISO timestamp (exact date with details on) |
| `deadline` \* | Application deadline (`validThrough`) |
| `description`, `descriptionHtml` \* | Full job description as plain text and HTML |
| `jobFunctions` \* | Job function categories, e.g. `Retail - Cashier` |
| `locations` \* | All districts the job covers |
| `employmentTerms`, `employmentTypeSchema` \* | All employment terms as labels and as schema.org values (`FULL_TIME`, `PART_TIME`, `CONTRACTOR`…) |
| `education` \* | Education requirements |
| `benefitsDetail` \* | Employer's full benefits list (5-day week, medical plan, bonus…) |
| `contactNo`, `contactPerson` \* | Employer contact details when published |
| `workPermit` \* | Work-permit requirement note |
| `language` | `en` or `zh` — the label language used for this run |
| `scrapedAt` | When the row was scraped |

\* only with **Include detail page data** on.

### District filter values

Use the English or Chinese name, or the code. Region codes: `1_r` All Hong Kong Island · `2_r` All Kowloon · `3_r` All New Territories · `4_r` All Outlying Islands.

**Hong Kong Island:** Aberdeen 香港仔 · Admiralty 金鐘 · Apleichau 鴨脷洲 · Causeway Bay 銅鑼灣 · Central 中環 · Central and Western District 中西區 · Chai Wan 柴灣 · Chung Hom Kok 舂磡角 · Cyberport 數碼港 · Eastern District 東區 · Fortress Hill 炮台山 · Happy Valley 跑馬地 · Kennedy Town 堅尼地城 · Mid Level 半山 · Morrison Hill 摩利臣山 · North Point 北角 · Pokfulam 薄扶林 · Quarry Bay 鰂魚涌 · Sai Wan Ho 西灣河 · Sai Ying Pun 西營盤 · Shau Kei Wan 筲箕灣 · Sheung Wan 上環 · Siu Sai Wan 小西灣 · Southern District 南區 · Stanley 赤柱 · Tai Tam 大潭 · Taikoo Shing 太古城 · The Peak 山頂 · Tin Hau 天后 · Wan Chai District 灣仔區 · Wanchai 灣仔 · Wong Chuk Hang 黃竹坑

**Kowloon:** Cheung Sha Wan 長沙灣 · Choi Hung 彩虹 · Diamond Hill 鑽石山 · Homantin 何文田 · Hunghom 紅磡 · Jordan 佐敦 · Kai Tak 啟德 · Kowloon Bay 九龍灣 · Kowloon City 九龍城 · Kowloon Tong 九龍塘 · Kwun Tong 觀塘 · Lai Chi Kok 荔枝角 · Lam Tin 藍田 · Lok Fu 樂富 · Mei Foo 美孚 · Mongkok 旺角 · Ngau Chi Wan 牛池灣 · Ngau Tau Kok 牛頭角 · Prince Edward 太子 · San Po Kong 新蒲崗 · Sham Shui Po 深水埗 · Shek Kip Mei 石硤尾 · Tai Kok Tsui 大角咀 · Tokwawan 土瓜灣 · Tsimshatsui 尖沙咀 · Tsimshatsui East 尖沙咀東 · Tsz Wan Shan 慈雲山 · Wong Tai Sin 黃大仙 · Yau Tong 油塘 · Yaumatei 油麻地 (plus the `… District` variants)

**New Territories:** Clearwater Bay 清水灣 · Fanling 粉嶺 · Fotan 火炭 · Hong Kong Science Park 香港科學園 · Kam Tin 錦田 · Kwai Chung 葵涌 · Kwai Fong 葵芳 · Kwai Hing 葵興 · Lai King 荔景 · Lo Wu 羅湖 · Lok Ma Chau 落馬洲 · Ma On Shan 馬鞍山 · Ma Wan 馬灣 · Pak Shek Kok 白石角 · Pat Heung 八鄉 · Sai Kung 西貢 · Shatin 沙田 · Shek Kong 石崗 · Shek Mun 石門 · Sheung Shui 上水 · Siu Lek Yuen 小瀝源 · Tai Po 大埔 · Tai Wai 大圍 · Tin Shui Wai 天水圍 · Tseung Kwan O 將軍澳 · Tsing Yi 青衣 · Tsuen Wan 荃灣 · Tuen Mun 屯門 · Yuen Long 元朗 (plus the `… District` variants)

**Outlying Islands:** Chek Lap Kok 赤鱲角 · Cheung Chau 長洲 · Discovery Bay 愉景灣 · HK International Airport 香港國際機場 · Islands District 離島區 · Lamma Island 南丫島 · Lantau 大嶼山 · Tung Chung 東涌

### Limitations

- Covers the PTgoodjobs channel only (about 2,500 live jobs, mostly frontline roles). The main CTgoodjobs board is not included
- Most frontline listings do not disclose pay — expect `salaryMin` / `salaryMax` to be filled on roughly 10–25 % of rows depending on the keyword, with `salaryText` showing `negotiable` or `N/A` on the rest
- Keyword search matches the site's own index; English and Chinese keywords can return different sets, so run both if coverage matters
- The site serves 16 jobs per page and this Actor waits about 1.2 s between requests (and between detail pages), so a 1,000-job export with details takes roughly 25 minutes

### Pricing model

You pay per result — a small fee for each job returned. A 200-job export costs less than a coffee, and you only pay for rows you actually receive.

### Legal

This Actor collects publicly available job postings for research, analytics and recruitment-intelligence purposes. You are responsible for using the data in line with CTgoodjobs' terms of use and applicable data-protection law.

# Actor input Schema

## `keyword` (type: `string`):

Job title, company or skill to search for, e.g. <code>sales</code>, <code>cashier</code>, <code>nurse</code>, <code>driver</code>, <code>收銀</code>, <code>文員</code>. English and Chinese both work. At least 2 characters.

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

Optional comma-separated Hong Kong districts, in English or Chinese exactly as CTgoodjobs spells them, e.g. <code>Mongkok, Tsimshatsui</code>, <code>Tsuen Wan</code>, <code>旺角</code>. Region-wide codes also work: <code>1\_r</code> Hong Kong Island, <code>2\_r</code> Kowloon, <code>3\_r</code> New Territories, <code>4\_r</code> Outlying Islands. Leave empty for all of Hong Kong.

## `employmentType` (type: `array`):

Optional. Only return jobs with these employment terms.

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

Language of the site labels in the output (district names, salary units, employment terms, benefits). Job titles and descriptions stay in whatever language the employer wrote them.

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

Maximum number of jobs to return (the site pages 16 at a time). Keep it small for a quick test, raise it for a full export.

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

Visit each job page to add the full description (text + HTML), exact posted date and application deadline, job functions, all districts, full employment terms, education requirements, benefits list, contact number / contact person and work-permit note. One extra request per job, so it is slower — the listing already includes title, company, district, salary, employment type and posting age without it.

## Actor input object example

```json
{
  "keyword": "sales",
  "location": "",
  "employmentType": [],
  "language": "en",
  "maxItems": 50,
  "includeDetails": false
}
```

# Actor output Schema

## `datasetItemsJson` (type: `string`):

All scraped records as a JSON array.

## `datasetItemsCsv` (type: `string`):

All scraped records as a CSV file.

## `datasetItemsXlsx` (type: `string`):

All scraped records as an Excel workbook.

## `dataset` (type: `string`):

The default dataset of this run in Apify Console.

# 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 = {
    "keyword": "sales",
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("youfuxu/ptgoodjobs-hongkong-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 = {
    "keyword": "sales",
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("youfuxu/ptgoodjobs-hongkong-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 '{
  "keyword": "sales",
  "maxItems": 50
}' |
apify call youfuxu/ptgoodjobs-hongkong-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,youfuxu/ptgoodjobs-hongkong-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/NyrN5HUw0kww16YXv/builds/wOOIGCt0u0if8eGy3/openapi.json
