
Zipcode Search
- 3.7k installs
- 6.5k repo stars
- Updated July 27, 2026
- nomadamas/k-skill
zipcode-search is a skill that looks up Korean postcodes and official English addresses from keywords using the ePost integrated search page.
About
zipcode-search queries the Korea Post official integrated postcode search to return zip codes and official English addresses for Korean address keywords. Use it when users need postcode plus English address for overseas payments, shipping forms, or bilingual address display. Prerequisites are internet access, curl, and python3. Inputs accept road name plus building number, city district plus road, or dong plus lot number keywords. The workflow hits https://www.epost.kr/search.RetrieveIntegrationNewZipCdList.comm with a keyword parameter, fetches HTML via curl with HTTP/1.1 TLS 1.2 and retries, then parses viewDetail zip roadAddress englishAddress jibunAddress tuples from the response. A shipped scripts/zipcode_search.py helper returns JSON with query and results array. Results normalize into postcode, Korean road address, official English address, optional jibun address, and top three to five candidates when multiple matches appear. Retry guidance tightens keywords from short road plus number through full city district address to dong plus lot number. Failure modes include markup changes breaking viewDetail parsing, overly broad queries, timeout without retries, and curl negotiati.
- Uses official ePost integrated search, not unofficial English address converters or blog formats.
- Parses viewDetail tuples for zip code, road address, English address, and jibun address.
- curl --http1.1 --tls-max 1.2 with retries recommended over bare urllib due to reset/timeouts.
- Shipped scripts/zipcode_search.py returns structured JSON for repeatable lookups.
- Retry ladder from short road keywords to full city district address to dong plus lot number.
Zipcode Search by the numbers
- 3,682 all-time installs (skills.sh)
- +128 installs in the week ending Jul 28, 2026 (Skillselion tracking)
- Ranked #117 of 2,742 Automation & Workflows skills by installs in the Skillselion catalog
- Security screen: HIGH risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
zipcode-search capabilities & compatibility
- Capabilities
- official epost integrated search queries · viewdetail html parsing for address tuples · json output via zipcode_search.py helper · multi candidate normalization and selection guid · keyword retry ladder for failed or broad searche
- Use cases
- api development
- Pricing
- Free
What zipcode-search says it does
우체국 공식 통합 우편번호 검색 페이지를 조회해서
viewDetail(zip, roadAddress, englishAddress, jibunAddress, rowIndex)
curl --http1.1 --tls-max 1.2
npx skills add https://github.com/nomadamas/k-skill --skill zipcode-searchAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 3.7k |
|---|---|
| repo stars | ★ 6.5k |
| Security audit | 2 / 3 scanners passed |
| Last updated | July 27, 2026 |
| Repository | nomadamas/k-skill ↗ |
How do I get the official Korean postcode and English address for a road name or dong address keyword?
Look up Korean postcodes and official English addresses from address keywords via the ePost integrated search page.
Who is it for?
Developers or agents filling overseas payment, shipping, or bilingual forms that need official Korea Post English address spelling.
Skip if: Skip for non-Korean addresses, unofficial romanization sources, or environments without curl and python3 network access.
When should I use this skill?
User asks for Korean postcode and English address, overseas payment address formatting, or ePost lookup for a Korean street keyword.
What you get
At least one postcode candidate with Korean road address, official English address, and optional jibun address formatted for user selection.
- korean postcode
- official english address
By the numbers
- Requires curl and python3 as prerequisites
- Supports three Korean address keyword input patterns
Files
Zipcode Search
What this skill does
우체국 공식 통합 우편번호 검색 페이지를 조회해서 주소 키워드에 맞는 우편번호와 공식 영문 주소를 함께 찾는다.
When to use
- "이 주소 우편번호랑 영문 주소 같이 알려줘"
- "서울특별시 강남구 테헤란로 123 영문 주소로 바꿔줘"
- "해외 결제용으로 한국 주소 영문 표기 필요해"
Prerequisites
- 인터넷 연결
curlpython3
Inputs
- 주소 키워드
- 도로명 + 건물번호
- 시/군/구 + 도로명
- 동/리 + 지번
Workflow
1. Query the official integrated ePost page first
비공식 영문주소 변환기나 블로그 표기를 쓰지 말고 아래 우체국 공식 통합 검색 페이지를 먼저 조회한다.
https://www.epost.kr/search.RetrieveIntegrationNewZipCdList.comm이 페이지는 keyword 파라미터로 우편번호, 국문 주소, English/집배코드 열의 공식 영문 주소를 함께 돌려준다.
2. Fetch the HTML with curl and extract the viewDetail(...) rows
현재 ePost 엔드포인트는 응답이 간헐적으로 reset/timeout 될 수 있으므로, 로컬 urllib 대신 curl --http1.1 --tls-max 1.2 + 재시도 경로를 기본 예시로 사용한다.
python3 - <<'PY'
import html
import re
import subprocess
query = "서울특별시 강남구 테헤란로 123"
cmd = [
"curl",
"--http1.1",
"--tls-max",
"1.2",
"--silent",
"--show-error",
"--location",
"--retry",
"3",
"--retry-all-errors",
"--retry-delay",
"1",
"--max-time",
"20",
"--get",
"--data-urlencode",
f"keyword={query}",
"https://www.epost.kr/search.RetrieveIntegrationNewZipCdList.comm",
]
page = subprocess.run(
cmd,
check=True,
capture_output=True,
text=True,
encoding="utf-8",
).stdout
matches = re.findall(
r"viewDetail\('([^']*)','([^']*)','([^']*)','([^']*)',\s*'[^']*'\)",
page,
)
if not matches:
raise SystemExit("검색 결과가 없습니다.")
for zip_code, road_address, english_address, jibun_address in matches[:5]:
print(zip_code)
print(html.unescape(road_address))
print(html.unescape(english_address))
print(html.unescape(jibun_address))
print("---")
PY핵심 값은 viewDetail(zip, roadAddress, englishAddress, jibunAddress, rowIndex) 인자다. 공식 출력은 보통 123, Teheran-ro, Gangnam-gu, Seoul, 06133, Rep. of KOREA 같은 형식을 그대로 준다.
3. Prefer the shipped helper for repeatable execution
저장소에는 같은 흐름을 감싼 실행 가능한 helper가 포함되어 있다.
python3 scripts/zipcode_search.py "서울특별시 강남구 테헤란로 123"
./scripts/zipcode_search.py "서울특별시 강남구 테헤란로 123"예시 출력:
{
"query": "서울특별시 강남구 테헤란로 123",
"results": [
{
"zip_code": "06133",
"road_address": "서울특별시 강남구 테헤란로 123 (역삼동, 여삼빌딩)",
"english_address": "123, Teheran-ro, Gangnam-gu, Seoul, 06133, Rep. of KOREA",
"jibun_address": "서울특별시 강남구 역삼동 648-23 (여삼빌딩)"
}
]
}4. Normalize for humans
응답은 raw HTML이므로 그대로 붙이지 말고 아래처럼 정리한다.
- 우편번호
- 도로명 국문 주소
- 공식 영문 주소
- 필요하면 지번 주소
- 후보가 여러 개면 상위 3~5개만 보여주고 어느 항목이 가장 근접한지 짚기
5. Retry with tighter and fuller keywords when needed
검색 결과가 없거나 timeout/reset이 반복되면 아래 순서로 재시도한다.
- 짧은 도로명 + 건물번호:
테헤란로 123 - 시/군/구 포함 전체 주소:
서울 강남구 테헤란로 123 - 동/리 + 지번 또는 대체 표기:
역삼동 648-23
6. Prefer temp files in wrapped shells
CLI 래퍼나 에이전트 쉘에서는 here-doc + Python one-liner가 깨질 수 있으므로, 실전에서는 mktemp 같은 임시 파일에 HTML을 저장한 뒤 그 파일을 파싱하는 경로를 우선한다. 응답 일부만 보려고 | head 를 붙이면 다운스트림이 먼저 닫히면서 curl: (23) 이 보일 수 있으니, 이 경우도 전체 응답을 임시 파일에 저장한 뒤 확인한다.
Done when
- 적어도 한 개의 우편번호 후보와 공식 영문 주소가 정리되어 있다
- 다중 후보일 때 사용자가 고를 수 있게 국문/영문 주소 차이가 보인다
- 검색 결과가 없으면 재검색 키워드 방향을 제안했다
Failure modes
- 우체국 검색 페이지 마크업이 바뀌면
viewDetail(...)추출 규칙이 깨질 수 있다 - 주소 키워드가 너무 넓으면 결과가 과하게 많아질 수 있다
- 재시도 없이 한 번만 호출하면 timeout/reset 같은 일시 오류가 날 수 있다
curl없이 다른 클라이언트로 바로 붙으면 협상/전송 오류가 날 수 있다
Notes
- 공식 표기 그대로 유지하는 조회형 스킬이다
- 상대 날짜/실시간 개념은 없으므로 주소 문자열 정제에 집중한다
#!/usr/bin/env python3
from __future__ import annotations
import argparse
import html
import json
import subprocess
from dataclasses import asdict, dataclass
import re
from typing import Callable, Sequence
SEARCH_URL = "https://www.epost.kr/search.RetrieveIntegrationNewZipCdList.comm"
DEFAULT_LIMIT = 5
VIEW_DETAIL_PATTERN = re.compile(
r"viewDetail\(\s*'(?P<zip>(?:\\'|[^'])*)'\s*,\s*'(?P<road>(?:\\'|[^'])*)'\s*,\s*'(?P<english>(?:\\'|[^'])*)'\s*,\s*'(?P<jibun>(?:\\'|[^'])*)'\s*,\s*'(?P<row>(?:\\'|[^'])*)'\s*\)",
re.S,
)
@dataclass(frozen=True)
class AddressSearchResult:
zip_code: str
road_address: str
english_address: str
jibun_address: str | None = None
@dataclass(frozen=True)
class AddressSearchResponse:
query: str
results: list[AddressSearchResult]
def to_json(self) -> str:
return json.dumps(
{
"query": self.query,
"results": [asdict(item) for item in self.results],
},
ensure_ascii=False,
indent=2,
)
def clean_text(value: str | None) -> str | None:
if value is None:
return None
cleaned = html.unescape(value).replace("\\'", "'")
cleaned = " ".join(cleaned.split()).strip()
return cleaned or None
def parse_search_results(page: str) -> list[AddressSearchResult]:
items: list[AddressSearchResult] = []
for match in VIEW_DETAIL_PATTERN.finditer(page):
zip_code = clean_text(match.group("zip"))
road_address = clean_text(match.group("road"))
english_address = clean_text(match.group("english"))
jibun_address = clean_text(match.group("jibun"))
if not zip_code or not road_address or not english_address:
continue
items.append(
AddressSearchResult(
zip_code=zip_code,
road_address=road_address,
english_address=english_address,
jibun_address=jibun_address,
)
)
return items
def build_search_command(query: str) -> list[str]:
return [
"curl",
"--http1.1",
"--tls-max",
"1.2",
"--silent",
"--show-error",
"--location",
"--retry",
"3",
"--retry-all-errors",
"--retry-delay",
"1",
"--max-time",
"20",
"--get",
"--data-urlencode",
f"keyword={query}",
SEARCH_URL,
]
Runner = Callable[..., subprocess.CompletedProcess[str]]
def fetch_search_page(query: str, *, runner: Runner = subprocess.run) -> str:
result = runner(
build_search_command(query),
check=True,
capture_output=True,
text=True,
encoding="utf-8",
)
return result.stdout
Fetcher = Callable[[str], str]
def lookup_korean_address(
query: str,
*,
limit: int = DEFAULT_LIMIT,
fetcher: Fetcher = fetch_search_page,
) -> AddressSearchResponse:
normalized_query = " ".join(query.split()).strip()
if not normalized_query:
raise ValueError("query must not be blank")
if limit <= 0:
raise ValueError("limit must be a positive integer")
page = fetcher(normalized_query)
return AddressSearchResponse(
query=normalized_query,
results=parse_search_results(page)[:limit],
)
def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
description="Look up Korean postcodes and official English addresses from ePost.",
)
parser.add_argument("query", help="Korean road-name or jibun address query")
parser.add_argument("--limit", type=int, default=DEFAULT_LIMIT, help="maximum number of rows to keep")
return parser
def main(argv: Sequence[str] | None = None) -> int:
parser = build_parser()
args = parser.parse_args(argv)
response = lookup_korean_address(args.query, limit=args.limit)
print(response.to_json())
return 0
if __name__ == "__main__":
raise SystemExit(main())
Related skills
How it compares
Choose zipcode-search over generic geocoding when Korea Post official postcode and English address strings are required for forms and payments.
FAQ
Which endpoint does zipcode-search query?
The official ePost integrated search at epost.kr/search.RetrieveIntegrationNewZipCdList.comm with a keyword parameter.
What tools does zipcode-search require?
Internet access, curl, and python3; the docs recommend curl with HTTP/1.1, TLS 1.2, and retry flags.
What if the search returns no results?
Retry with tighter then fuller keywords: short road plus number, full city district address, then dong plus lot number.
Is Zipcode Search safe to install?
skills.sh reports 2 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.