JobThai Scraper - Thailand Job Postings avatar

JobThai Scraper - Thailand Job Postings

Pricing

from $1.00 / 1,000 item extracteds

Go to Apify Store
JobThai Scraper - Thailand Job Postings

JobThai Scraper - Thailand Job Postings

Scrape job postings from JobThai and get each one as JSON with salary min/max in THB, pay period, seniority, required years of experience, skills and remote status parsed by AI. Handles Thai-language postings. First 10 items enriched free.

Pricing

from $1.00 / 1,000 item extracteds

Rating

0.0

(0)

Developer

Kusol Sukhakul

Kusol Sukhakul

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

2

Monthly active users

4 days ago

Last modified

Categories

Share

Thailand Job Postings Scraper

Scrapes Thai job postings from JobThai and returns each one as structured JSON, with salary range, seniority, required experience, skills and remote status normalized by an AI step into fields you can filter and aggregate.

No setup, no API key

Run it with the defaults. Every posting comes back with the full ai block filled in; there is no key to request and nothing to configure. You pay per posting returned and per posting the AI step enriched successfully, at the prices on this listing, and nothing for an AI step that fails. To see the output before a large run, set maxItems to 10 — about $0.03 at the current prices.

enrich: false returns the postings without the AI step, and without its charge.

Sample output

One item, exactly as it lands in the dataset:

{
"url": "https://www.jobthai.com/th/company/job/1936578",
"source": "jobthai",
"scrapedAt": "2026-09-05T08:44:49+00:00",
"title": "SALE & RECEPTION",
"company": "ANY1 Fitness & Sports (บริษัท ธนสุวรรณ กรุ๊ป จำกัด)",
"location": "บางแค, กรุงเทพมหานคร, TH",
"employmentType": "FULL_TIME",
"salaryText": "11000-15000 THB MONTH",
"postedAt": "2026-09-05T08:41:54.000Z",
"description": "รายละเอียดงาน / หน้าที่รับผิดชอบ:- ต้อนรับ ให้ข้อมูลเกี่ยวกับบริการ สิทธิประโยชน์ และแพ็กเกจสมาชิกแก่ลูกค้าที่เข้ามาใช้บริการ- นำเสนอขายแพ็กเกจสมาชิก/คอร์สออกกำลังกายให้บรรลุเป้าหมายยอดขาย …",
"jobId": "1936578",
"ai": {
"salary_min_thb": 11000,
"salary_max_thb": 15000,
"salary_period": "monthly",
"seniority": "entry",
"experience_years_min": null,
"skills": [
"การต้อนรับ",
"การนำเสนอขาย",
"การดูแลงานเอกสาร",
"การลงทะเบียนสมาชิก",
"การรับชำระเงิน",
"การติดตามลูกค้า",
"การประสานงาน",
"การส่งรายงานยอดขาย"
],
"remote_status": "onsite"
}
}

Everything outside ai is read from the posting. Everything inside ai is inferred from the posting text by the AI step. When enrichment is turned off, fails, or times out, ai is null, an aiError field says why, and the posting is returned anyway.

Note: the whole object above, ai included, is verbatim from a live make actor-run against jobthai.com and the deployed enrichment service on 2026-09-05, with the description truncated for length. Of the 3 items that run scraped, this one enriched cleanly; one of the other two hit a transient 503 from the enrichment service and came back with ai: null and an aiError, per the "return the raw item uncharged for AI" rule below.

Pay only for what changed

Turn on incremental and schedule the Actor daily or weekly. The first run returns everything; each later run returns only postings that are new or whose content changed since the last run with the same stateName, marked changeType: "NEW" or "UPDATED". Unchanged postings are skipped: not returned, not charged, not sent to the AI step.

{ "incremental": true, "stateName": "weekly-eng" }
  • Use a different stateName for each separate search or schedule.
  • The memory lives in a key-value store in your own Apify account and forgets postings not seen for 30 days.
  • A posting whose AI step failed is not remembered, so the next run tries it again.
  • Closed postings are not reported; a posting that disappears is simply not returned.

Input

OptionTypeDefaultWhat it does
startUrlsarrayJobThai job listing pageListing or job pages to start from. Listing pages are followed to the jobs they link to.
maxItemsinteger100Hard cap on items returned. Never exceeded. Maximum 1000.
enrichbooleantrueTurns the paid AI step on or off.
enrichFieldsarrayall fieldsRestricts enrichment to named fields: salary_min_thb, salary_max_thb, salary_period, seniority, experience_years_min, skills, remote_status.
incrementalbooleanfalseReturn only postings that are new or changed since the last run with the same stateName. Unchanged ones are not charged.
stateNamestringdefaultSeparate incremental memories, e.g. one per schedule.
talariaTokenstring (secret)noneNot needed on Apify. Only for running the Actor outside Apify, or against your own talariaBaseUrl.
talariaBaseUrlstringhttps://talaria.skusol.comPoint the AI step at your own endpoint instead.
requestIntervalSecsinteger1Minimum seconds between two requests to the target site.
maxRetriesinteger3Retries per page before it is skipped.
respectRobotsTxtbooleantrueStops the crawl if robots.txt disallows it.

Use cases

  1. Salary benchmarking. Postings state salary as free text, in several formats and two languages. salary_min_thb, salary_max_thb and salary_period give you numbers you can average per role and per province.
  2. Skill demand tracking. Run the same query weekly and count skills across items to see which tools employers are actually asking for, rather than which ones a survey says they want.
  3. Recruitment lead lists. Filter by seniority, remote_status and experience_years_min to find the companies hiring for the roles you place, with a link back to each posting.

Pricing

Prices are set on the Apify Store listing; this table says what triggers each event.

EventCharged when
apify-actor-startOnce, when a run starts.
item-scrapedOnce per job posting after it has been written to the dataset. A posting that fails to parse is never pushed and never charged.
ai-enriched-itemOnce per posting whose AI fields came back valid. Enrichment that fails, times out or is turned off is not charged.

Two rules the actor holds to: nothing is charged before the thing it pays for exists, and when a run reaches its maximum cost the run ends cleanly with everything produced so far.

Limitations

  • Rate. With enrichment on, throughput is bounded by the AI service. The Actor enriches three postings at a time, roughly 15 per minute, so a 100-item run takes about 7 minutes. With enrich: false the limit is the polite crawl delay, one page per second by default.
  • Coverage. JobThai only. Listing pages are followed one level to the job pages they link to; pagination beyond the pages you pass in startUrls is not crawled. Postings missing a title or description are skipped rather than returned half-empty.
  • Freshness. Each item is a snapshot at scrapedAt. Without incremental, a posting scraped on two runs appears, and is charged, on both; with it, only new or changed postings come back.
  • AI fields are inferred. ai values come from a language model reading the posting. A field the posting does not state comes back null or unknown rather than a guess, but the values are not verified against any other source. salaryText keeps the original wording so you can check.
  • Personal data. Only posting content is collected: role, employer, location, salary, requirements. Contact people named on a posting are not extracted.
  • robots.txt. With respectRobotsTxt on, a disallow ends the crawl instead of working around it.

Development

make actor-setup # once, needs the network
make build # go build/vet/test, then compileall and pytest for the actor
make actor-run # local run in pay-per-event test mode

The test suite runs offline. It uses fake pages, a fake enrichment service, and the Apify SDK's local pay-per-event mode, and asserts on charge counts and ordering.