npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

thai-postal-code

v0.1.2

Published

TypeScript library to autofill Thai province and district from postal code, with subdistrict listing support

Readme

thai-postal-code

Searching Thai addresses by postal code to autofill province and district, with a list of subdistricts. ค้นหาที่อยู่ด้วยรหัสไปรษณีย์ สำหรับ autofill จังหวัด และ อำเภอ พร้อมรายการตำบล

Thai postal code lookup for address autofill — province, district, and subdistricts with bilingual names. ค้นหารหัสไปรษณีย์ไทย สำหรับกรอกที่อยู่อัตโนมัติ — จังหวัด อำเภอ และตำบล พร้อมชื่อสองภาษา

CI npm JSR License: MIT


Input a 5-digit Thai postal code, get back the province, district, and a ready-to-use list of subdistricts — all with Thai and English names. Coordinates included where available.

Synchronous, zero dependencies, works in Node.js, Bun, Deno, and the browser.


Install

# npm
npm install thai-postal-code

# Bun
bun add thai-postal-code

# JSR (Deno / Bun / Node)
npx jsr add @antronic/thai-postal-code
deno add jsr:@antronic/thai-postal-code

# CDN (browser, no bundler)
import { autofillByPostalCode } from "https://esm.sh/thai-postal-code";

Quick start

import { autofillByPostalCode } from "thai-postal-code";

const result = autofillByPostalCode("10330");

result.provinceNameTh  // "กรุงเทพมหานคร"
result.provinceNameEn  // "Bangkok"
result.districtNameTh  // "ปทุมวัน"
result.districtNameEn  // "Pathum Wan"
result.subdistricts
// [
//   { subdistrictNameTh: "ลุมพินี",  subdistrictNameEn: "Lumphini",  subdistrictCode: 103007 },
//   { subdistrictNameTh: "วังใหม่",   subdistrictNameEn: "Wang Mai",   subdistrictCode: 103008 },
//   { subdistrictNameTh: "รองเมือง", subdistrictNameEn: "Rong Mueang", subdistrictCode: 103006 },
// ]

Note: all functions are synchronous. No await needed.


Runtime support

| Runtime | Support | |---------|---------| | Node.js ≥ 18 | ✓ | | Bun ≥ 1.0 | ✓ | | Deno (via JSR) | ✓ | | Browser (ESM) | ✓ | | TypeScript | ✓ Full types exported |


API

lookupByPostalCode(postalCode, options?)

Full lookup — returns province, district, subdistricts, and coordinates.

Uses the pre-built postal index. O(1) hash map lookup.

import { lookupByPostalCode } from "thai-postal-code";

const result = lookupByPostalCode("50000");
// {
//   postalCode:     "50000",
//   provinceNameTh: "เชียงใหม่",
//   provinceNameEn: "Chiang Mai",
//   districtNameTh: "เมืองเชียงใหม่",
//   districtNameEn: "Mueang Chiang Mai",
//   subdistricts:   [{ subdistrictNameTh: "ช้างคลาน", subdistrictNameEn: "Chang Khlan", subdistrictCode: 500103 }, ...],
//   lat:            18.7883439,
//   lng:            98.9929882
// }

Throws by default for unknown or invalid input. Pass { silent: true } to return null instead.


autofillByPostalCode(postalCode, options?)

Same as lookupByPostalCode but omits lat and lng. Use when you only need to fill address fields.

import { autofillByPostalCode } from "thai-postal-code";

const fill = autofillByPostalCode("76000", { silent: true });
if (fill) {
  fill.provinceNameTh  // "เพชรบุรี"
  fill.districtNameTh  // "เมืองเพชรบุรี"
  fill.subdistricts    // SubdistrictEntry[]
}

getSubdistrictsByPostalCode(postalCode)

Returns only the subdistrict list. Never throws — returns [] for unknown codes.

import { getSubdistrictsByPostalCode } from "thai-postal-code";

getSubdistrictsByPostalCode("10330")
// [
//   { subdistrictNameTh: "ลุมพินี", subdistrictNameEn: "Lumphini", subdistrictCode: 103007 },
//   ...
// ]

searchAddress(query, limit?)

Substring search across Thai and English names for province, district, and subdistrict, and the postal code itself. Case-insensitive for English fields.

Default limit: 20. Returns ThaiSearchResult[] which includes lat and lng.

import { searchAddress } from "thai-postal-code";

searchAddress("สีลม")     // Thai name match
searchAddress("Silom")    // English match (case-insensitive)
searchAddress("10500")    // postal code match
searchAddress("Silom", 5) // limit to 5 results

listProvinces()

All 77 Thai provinces, sorted by Thai name.

import { listProvinces } from "thai-postal-code";

listProvinces()
// [
//   { nameTh: "กระบี่",         nameEn: "Krabi" },
//   { nameTh: "กรุงเทพมหานคร", nameEn: "Bangkok" },
//   ...
// ]

listDistrictsByProvince(provinceNameTh)

All districts for a province, sorted by Thai name. Each entry includes the district's postal code.

import { listDistrictsByProvince } from "thai-postal-code";

listDistrictsByProvince("เชียงใหม่")
// [
//   { nameTh: "กัลยาณิวัฒนา", nameEn: "Galyani Vadhana", postalCode: "58130" },
//   { nameTh: "จอมทอง",        nameEn: "Chom Thong",       postalCode: "50160" },
//   ...
// ]

listAllPostalCodes()

All postal codes in the dataset, sorted ascending. Sourced from the postal index keys.

import { listAllPostalCodes } from "thai-postal-code";

listAllPostalCodes()
// ["10100", "10110", "10120", ...]

LookupOptions

| Option | Type | Default | Description | |--------|------|---------|-------------| | silent | boolean | false | Return null instead of throwing for unknown or invalid input |


TypeScript types

import type {
  RawThaiRecord,      // raw bundled row (10 fields + lat/lng)
  SubdistrictEntry,   // { subdistrictNameTh, subdistrictNameEn, subdistrictCode }
  ThaiAddressResult,  // full result with subdistricts + lat/lng
  ThaiAutofillResult, // result without lat/lng
  ThaiSearchResult,   // flat row from searchAddress() with lat/lng
  LookupOptions,      // { silent?: boolean }
} from "thai-postal-code";

Framework examples

React

import { useState } from "react";
import { autofillByPostalCode, type SubdistrictEntry } from "thai-postal-code";

export function AddressForm() {
  const [province, setProvince] = useState("");
  const [district, setDistrict] = useState("");
  const [subdistricts, setSubdistricts] = useState<SubdistrictEntry[]>([]);
  const [selectedSub, setSelectedSub] = useState("");

  function handlePostalInput(code: string) {
    if (code.length !== 5) return;
    const result = autofillByPostalCode(code, { silent: true });
    if (!result) return;
    setProvince(result.provinceNameTh);
    setDistrict(result.districtNameTh);
    setSubdistricts(result.subdistricts);
    setSelectedSub(result.subdistricts[0]?.subdistrictNameTh ?? "");
  }

  return (
    <div>
      <input
        placeholder="รหัสไปรษณีย์"
        maxLength={5}
        onChange={(e) => handlePostalInput(e.target.value)}
      />
      <input value={province} readOnly placeholder="จังหวัด" />
      <input value={district} readOnly placeholder="อำเภอ / เขต" />
      <select
        value={selectedSub}
        onChange={(e) => setSelectedSub(e.target.value)}
      >
        {subdistricts.map((s) => (
          <option key={s.subdistrictCode} value={s.subdistrictNameTh}>
            {s.subdistrictNameTh}
          </option>
        ))}
      </select>
    </div>
  );
}

Vue 3

<script setup lang="ts">
import { ref } from "vue";
import { autofillByPostalCode, type SubdistrictEntry } from "thai-postal-code";

const province = ref("");
const district = ref("");
const subdistricts = ref<SubdistrictEntry[]>([]);

function onPostalInput(code: string) {
  if (code.length !== 5) return;
  const result = autofillByPostalCode(code, { silent: true });
  if (!result) return;
  province.value = result.provinceNameTh;
  district.value = result.districtNameTh;
  subdistricts.value = result.subdistricts;
}
</script>

Data sources

Primary — address data

thailand-geography-json by thailand-geography-data https://github.com/thailand-geography-data/thailand-geography-json

Provides all 77 provinces, 928 districts, and 7,436 sub-districts with Thai and English names, joined by postal code across three files (provinces.json, districts.json, subdistricts.json).

Secondary — coordinates

Thai-zip-code-latitude-and-longitude by @rathpanyowat https://github.com/rathpanyowat/Thai-zip-code-latitude-and-longitude

Provides a representative lat/lng per postal code. Merged at bundle time by postal code. Codes absent from this dataset have lat: null, lng: null.


Special thanks

Thank you to thailand-geography-data for maintaining a comprehensive, bilingual, and actively updated dataset of Thai geographical data, and to @rathpanyowat for the postal code coordinate dataset. This library is built entirely on their work.


Contributing

bun install
bun run data:pipeline   # fetch all sources, join, validate
bun run build:check:all # type-check src/ and scripts/
bun test
bun run build

Do not commit src/data/thai-postal-code.data.ts — it is auto-generated and gitignored.


License

MIT