""" URA GLS Map API — Full Sample ============================== Shows exactly what the API returns with all headers and data. Run from any IP (ArcGIS endpoints are publicly accessible). """ import json import requests # --------------------------------------------------------------------------- # Config (from Env.js) # --------------------------------------------------------------------------- ESERVICE = "https://eservice.ura.gov.sg" MAP_HOST = "https://maps.ura.gov.sg" ONEMAP = "https://www.onemap.gov.sg" session = requests.Session() session.headers.update({ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", "Referer": f"{ESERVICE}/maps/", "Origin": ESERVICE, }) def show(label, resp): """Print full request/response details.""" print(f"\n{'='*70}") print(f" {label}") print(f"{'='*70}") print(f" URL: {resp.url}") print(f" Status: {resp.status_code}") print(f"\n --- Request Headers ---") for k, v in resp.request.headers.items(): print(f" {k}: {v}") print(f"\n --- Response Headers ---") for k, v in resp.headers.items(): print(f" {k}: {v}") print(f"\n --- Response Body ---") try: data = resp.json() print(json.dumps(data, indent=2, ensure_ascii=False)[:5000]) return data except Exception: print(resp.text[:3000]) return None # --------------------------------------------------------------------------- # 1. Get OneMap auth token (JSONP) # --------------------------------------------------------------------------- print(f"\n{'#'*70}") print(f" STEP 1: Get OneMap Auth Token") print(f"{'#'*70}") token_resp = session.get(f"{ESERVICE}/sharedServicesWeb/onemapService/getOnemapToken", timeout=15) print(f"\n URL: {token_resp.url}") print(f" Status: {token_resp.status_code}") print(f" Raw response (JSONP): {token_resp.text[:200]}") # Parse JSONP text = token_resp.text.strip() if "(" in text: start = text.index("(") + 1 end = text.rindex(")") text = text[start:end] token_data = json.loads(text) onemap_token = token_data["token"]["token"] print(f"\n Parsed token: {onemap_token[:60]}...") print(f" Expiry: {token_data['token']['expiry']}") session.headers["Authorization"] = onemap_token # --------------------------------------------------------------------------- # 2. URA GLS — Layer Metadata # --------------------------------------------------------------------------- show( "STEP 2: URA GLS Layer Metadata (what fields exist)", session.get(f"{MAP_HOST}/ArcGis/rest/services/lsag/ura_sale_sites/MapServer/0", params={"f": "json"}, timeout=15), ) # --------------------------------------------------------------------------- # 3. URA GLS — Query actual parcel data # --------------------------------------------------------------------------- show( "STEP 3: URA GLS Parcels (first 3, all fields)", session.get( f"{MAP_HOST}/ArcGis/rest/services/lsag/ura_sale_sites/MapServer/0/query", params={ "where": "1=1", "outFields": "*", "f": "json", "resultRecordCount": "3", }, timeout=15, ), ) # --------------------------------------------------------------------------- # 4. URA GLS — Query with filter (upcoming sites only) # --------------------------------------------------------------------------- show( "STEP 4: URA GLS — Filtered (SITE_STATUS = 'Launched')", session.get( f"{MAP_HOST}/ArcGis/rest/services/lsag/ura_sale_sites/MapServer/0/query", params={ "where": "SITE_STATUS='Launched for Sale'", "outFields": "NAME_GLS,LOCATION,DEVT_ALLOW,GPR,GFA,SA_SQM,LEASE_YR,DATE_LNCH,DATE_CLOSG,SITE_STATUS", "f": "json", "resultRecordCount": "10", }, timeout=15, ), ) # --------------------------------------------------------------------------- # 5. HDB Sale Sites # --------------------------------------------------------------------------- show( "STEP 5: HDB Sale Sites (first 3)", session.get( f"{MAP_HOST}/ArcGis/rest/services/lsag/hdb_sale_sites2/MapServer/0/query", params={ "where": "1=1", "outFields": "*", "f": "json", "resultRecordCount": "3", }, timeout=15, ), ) # --------------------------------------------------------------------------- # 6. JTC Sale Sites # --------------------------------------------------------------------------- show( "STEP 6: JTC Sale Sites (first 3)", session.get( f"{MAP_HOST}/arcgis/rest/services/lsag/jtc_sale_sites/MapServer/0/query", params={ "where": "1=1", "outFields": "*", "f": "json", "resultRecordCount": "3", }, timeout=15, ), ) # --------------------------------------------------------------------------- # 7. OneMap Reverse Geocode (with auth header) # --------------------------------------------------------------------------- show( "STEP 7: OneMap Reverse Geocode (Orchard Road)", session.get( f"{ONEMAP}/api/public/revgeocode", params={"location": "1.3004,103.8460", "addressType": "all", "otherFeatures": "Y"}, timeout=15, ), ) # --------------------------------------------------------------------------- # 8. Map Export URL (server-rendered map image) # --------------------------------------------------------------------------- print(f"\n{'#'*70}") print(f" STEP 8: Map Export URLs (open in browser)") print(f"{'#'*70}") # Bounding box for Singapore (SVY21 coordinates) # xmin,ymin,xmax,ymax bboxes = { "Central Singapore": "28000,30000,32000,34000", "Full Singapore": "5000,25000,50000,50000", } for name, bbox in bboxes.items(): url = f"{MAP_HOST}/ArcGis/rest/services/lsag/ura_sale_sites/MapServer/export?f=image&bbox={bbox}&size=800,600&format=png&transparent=false" print(f"\n {name}:") print(f" {url}") print(f"\n Open any of these URLs in your browser to see the GLS parcels map!")