Israel Post Appointment
Three sub-flows:
- check-next — report earliest available slot for (branch, service). Read-only.
- book — book at earliest slot or a user-specified slot; returns confirmation details.
- cancel — cancel a just-booked appointment (from the same session).
Surprising facts (confirmed by capture)
- No ID / teudat zehut required. Only a mobile phone number.
- No SMS OTP. Phone is trust-on-first-use; identification happens physically at the branch's queue terminal by typing the phone.
- No captcha, no login. Fully anonymous flow.
- Headless Chromium works end-to-end despite Reblaze-style anti-bot on the page; no stealth plugin required.
Branch lookup (data/branches.json)
Bundled dataset of 314 booking-capable branches (Israel Post has ~1,524 branches total; only those with counter-appointment support are shipped here).
Each branch has: branchnumber, branchname, branchtypename, city, street, house, zip, area, region, telephone, geocode_latitude, geocode_longitude, ExtraServices.
Lookup pattern:
- Filter
branchesbycity+ fuzzy match onbranchname/street. - Confirm the match with the user (show full name + address).
- Use the matched branch's
branchnumberto construct the booking URL.
Do NOT ask the user for the branch number — resolve it from the name or address.
Booking URL
The URL-encoded template is bundled in data/branches.json under booking_url_template. Substitute {branchnumber} with the target branch's branchnumber field. Example:
https://israelpost.co.il/{encoded-hebrew-path}?no=101
Service selection
Four service types are exposed as buttons on the picker page:
| Service key | Hebrew label | Notes |
|---|---|---|
general |
אשנב כל | General counter, up to 10 slips per appointment |
forex |
מטבע חוץ | Foreign currency |
package_pickup |
מסירת דואר ללקוח | Package / mail pickup — the most common |
vehicle_transfer |
העברת בעלות רכב | Vehicle ownership transfer |
Not every branch offers every service — the buttons render per branch.
Flow (driven in headless Playwright)
gotothe booking URL with?no={branchnumber}.- Dismiss cookie overlay if present —
role=button[name="סגירה"](visible textהבנתי). - Click the service button by Hebrew label (class
.LeadAppt-services-item). - Date/time picker renders:
- Day tabs — only days with availability appear (e.g. "ראשון 26").
- Daypart tabs —
#LeadAppt-datepick-time-dayparts button[data-for="noon"]andbutton[data-for="afterNoon"]. The.activeone is currently shown; the default is the afternoon tab if it has slots. - Slot buttons — 3-minute intervals, labeled
HH:MM, inside the active daypart only.
- Select day tab → daypart tab → slot button.
- Click continue —
#LeadAppt-datepick-btn-next(firesLeadApptSubmit()). - Phone form:
- Primary input:
#leadmobile - Confirm:
role=textbox[name="*הקלדה חוזרת של מספר טלפון סלולארי"] - Both required; must match.
- Primary input:
- Click continue.
- Confirmation page — look for heading text
פגישתך נקבעה בהצלחה("your appointment has been successfully booked"). Read back:- Branch name + address
- Service
- Day, date (DD-MM-YYYY), time (HH:MM)
- Masked phone (e.g.
0501****76)
Cancel sub-flow
From the confirmation page:
- Click
role=button[name="בטל תור"]on the confirmation card. - An overlay appears: heading
האם ברצונך לבטל את התור?, buttonsבטל תור(confirm) /לא(abort). - Click the overlay's
בטל תור. - Success overlay with text
פגישתך בוטלה בהצלחה. Aחזורbutton closes it.
Cross-session cancel by phone lookup is not currently supported by this skill — the cancel button only appears on the in-session confirmation page.
Local preferences (~/.config/israel-agent-skills/preferences.yaml)
User values are read from a local, gitignored config — never hardcode in the skill.
israel_post:
default_branch_no: 101 # e.g. 101 = מרכזי ירושלים, יפו 23
default_service: package_pickup # one of: general | forex | package_pickup | vehicle_transfer
default_phone: "05XXXXXXXX" # treated as a secret
If the config is missing or default_phone is absent, the book flow must fail with a clear "run the onboard step first" message rather than prompting or defaulting.
Implementation notes
- Chromium headless=true with a realistic user-agent and default viewport is sufficient — no stealth plugin needed.
- For
check-next: stop after the daypart/slot tabs render. Extract the first day-tab label + first enabled slot button under the first non-empty daypart. Do not click anything further — avoids any risk of triggering a booking. - For
book: perform the full flow. Require an explicit user confirmation of the summary (branch, service, day/date/time, phone tail digits) before clicking the final continue button. Verifyפגישתך נקבעה בהצלחהbefore reporting success. - For
cancel: run from the confirmation page only. Verifyפגישתך בוטלה בהצלחהbefore reporting success. - If the Reblaze challenge ever escalates and headless stops working, fall back to a visible Playwright window; do not try to solve the challenge programmatically.
Refreshing data/branches.json
The bundled dataset can go stale (branches added, renumbered, or decommissioned). Refresh is a maintainer task; the upstream source and refresh script are maintained in the skill's development repo, not in this public plugin. If a branch lookup fails or the dataset is older than ~6 months, flag it to the user rather than silently returning stale data.