Capture the verified KOBUS non-member flow in a reusable helper that searches schedules, creates a temporary seat hold, saves an official payment-page autosubmit helper, and records cancellation fields. Constraint: KOBUS requires session-backed POST fields and returns pcpyNoAll/satsNoAll from setPcpy.ajax before checkout entry. Rejected: Opening payment page by URL alone | stplcfmpym.do requires the selected schedule, fare, seat, and hold POST body. Confidence: high Scope-risk: narrow Directive: Never submit card/payment fields automatically; cancel abandoned holds with cancPcpy.ajax. Tested: python3 -m py_compile express-bus-booking/scripts/kobus_express_booking.py; live 서울 센트럴시티(021)→광주 유스퀘어(500) 20260520 --hold-first-seat returned MSG_CD=S0000 pcpyNoAll and rendered payment-info page; /mrs/cancPcpy.ajax returned MSG_CD=S0000; ./scripts/validate-skills.sh Not-tested: final payment submission, mobile in-app browser behavior, mixed passenger discounts Co-authored-by: OpenAI Codex <codex@openai.com> Co-authored-by: OmX <omx@oh-my-codex.local>
3.2 KiB
KOBUS HTTP/API Probe Notes
Session-proven on 2026-05-08. Goal: avoid browser automation where possible.
Base
https://www.kobus.co.kr
Use a desktop User-Agent, HTTP/1.1 if needed, a cookie jar, and referers.
Tested Flow
Route / Terminal Candidates
POST /mrs/readRotLinInf.ajax
Observed JSON keys:
tfrLen
tfrInfList
len
codeYn
rotInfList
One probe returned about 1,208 route records in rotInfList.
Timetable
POST /mrs/alcnSrch.do
Example tested route/date:
서울경부(010) -> 부산(700), 2026-05-09
Observed result:
42 schedule links/cards
25 selectable seat snippets
first selectable: 00:30 / 천일고속 / 심야우등 / 10 seats
Typical POST fields:
deprCd=010
arvlCd=700
pathDvs=sngl
pathStep=1
deprDtm=YYYYMMDD
busClsCd=0
rtrpChc=1
timeLinkMin=00
timeLinkMax=23
Parse fnSatsChc(...) onclick values for the next step. Example:
fnSatsChc('20260509','003000','003000','010','700','3','07','0','Y','N','010','700','N','N','N','N')
Seat / Fare Stage
POST /mrs/satschc.do
Send the original alcnSrchFrm hidden fields plus selected values from fnSatsChc(...), including values such as:
deprTime=003000
alcnDeprTime=003000
alcnDeprTrmlNo=010
alcnArvlTrmlNo=700
indVBusClsCd=3
cacmCd=07
dcDvsCd=0
prvtBbizEmpAcmtRt=N
chldSftySatsYn=N
dsprSatsYn=N
Observed response contained form#satsChcFrm and hidden values:
{
"deprTime": "003000",
"alcnDeprTrmlNo": "010",
"alcnArvlTrmlNo": "700",
"adltFee": "47600",
"rmnSatsNum": "10",
"totSatsNum": "28"
}
Temporary Hold
POST /mrs/setPcpy.ajax
Observed successful response markers:
MSG_CD=S0000
pcpyNoAll
satsNoAll
ESTM_AMT
DC_AMT
TISSU_AMT
Hold Cancellation
POST /mrs/cancPcpy.ajax
Observed success marker:
MSG_CD=S0000
2026-05-13 서울→광주 re-verification: 센트럴시티(서울)(021) -> 광주(유·스퀘어)(500), 2026-05-20 00:45 중앙고속 심야우등, seat 1. /mrs/setPcpy.ajax returned MSG_CD=S0000, pcpyNoAll, satsNoAll=01, TISSU_AMT=36900; /mrs/stplcfmpym.do?keep=/mrs/pay rendered the official payment-information page; /mrs/cancPcpy.ajax returned MSG_CD=S0000.
Checkout Entry
POST /mrs/stplcfmpym.do
The POST body must include the selected schedule/seat form values plus temporary hold identifiers and fare amounts. A helper page can auto-submit this form to the official KOBUS endpoint.
For mobile browsers, use:
POST /mrs/stplcfmpym.do?keep=/mrs/pay
This preserves the POST body while placing /mrs/pay in location.href, which avoids a KOBUS client-side mobile redirect condition observed in the common JavaScript.
Interpretation
- Login was not required for route lookup, timetable lookup, seat-selection-page entry, temporary hold, or checkout-entry page display in the tested flow.
- Page HTML can include login or
grecaptchaTokenforms, but these did not block the tested lookup/seat-stage path. - Final payment should remain a manual, explicitly confirmed stage.
- KOBUS mobile behavior is less stable than desktop because common JavaScript can redirect narrow screens to the mobile main page.