JobThai Scraper - Thailand Job Postings
Pricing
from $1.00 / 1,000 item extracteds
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
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 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.
Try it free, no setup
Run it with the defaults. The first 10 postings come back with the full ai
block filled in, so you can see exactly what the AI step produces before
deciding whether it is worth anything to you. Postings past the tenth are
still returned in full — only the ai block is left empty, with aiError
saying why.
To enrich every posting in a run, put your own talariaToken in the input.
There is no signup wall on the demo and no card required to see the output.
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,
aiincluded, is verbatim from a livemake actor-runagainst 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 transient503from the enrichment service and came back withai: nulland anaiError, per the "return the raw item uncharged for AI" rule below.
Input
| Option | Type | Default | What it does |
|---|---|---|---|
startUrls | array | JobThai job listing page | Listing or job pages to start from. Listing pages are followed to the jobs they link to. |
maxItems | integer | 100 | Hard cap on items returned. Never exceeded. Maximum 1000. |
enrich | boolean | true | Turns the paid AI step on or off. |
enrichFields | array | all fields | Restricts enrichment to named fields: salary_min_thb, salary_max_thb, salary_period, seniority, experience_years_min, skills, remote_status. |
talariaToken | string (secret) | none | Bearer token for the enrichment service. Required when enrich is on. |
talariaBaseUrl | string | https://talaria.skusol.com | Point the AI step at your own endpoint instead. |
requestIntervalSecs | integer | 1 | Minimum seconds between two requests to the target site. |
maxRetries | integer | 3 | Retries per page before it is skipped. |
respectRobotsTxt | boolean | true | Stops the crawl if robots.txt disallows it. |
Use cases
- Salary benchmarking. Postings state salary as free text, in several
formats and two languages.
salary_min_thb,salary_max_thbandsalary_periodgive you numbers you can average per role and per province. - Skill demand tracking. Run the same query weekly and count
skillsacross items to see which tools employers are actually asking for, rather than which ones a survey says they want. - Recruitment lead lists. Filter by
seniority,remote_statusandexperience_years_minto 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.
| Event | Charged when |
|---|---|
apify-actor-start | Once, when a run starts. |
item-scraped | Once 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-item | Once 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, which
handles roughly six items per minute. A 100-item run with enrichment takes
about 20 minutes. With
enrich: falsethe 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
startUrlsis not crawled. Postings missing a title or description are skipped rather than returned half-empty. - Freshness. Each item is a snapshot at
scrapedAt. There is no change detection or deduplication across runs; a posting scraped twice appears twice. - AI fields are inferred.
aivalues come from a language model reading the posting. A field the posting does not state comes backnullorunknownrather than a guess, but the values are not verified against any other source.salaryTextkeeps 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
respectRobotsTxton, a disallow ends the crawl instead of working around it.
Development
make actor-setup # once, needs the networkmake build # go build/vet/test, then compileall and pytest for the actormake 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.