<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: HelloRoam</title>
    <description>The latest articles on DEV Community by HelloRoam (@helloroam).</description>
    <link>https://dev.to/helloroam</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3741224%2F3388ce93-4fac-4a8a-817e-06bd5b4a625c.png</url>
      <title>DEV Community: HelloRoam</title>
      <link>https://dev.to/helloroam</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/helloroam"/>
    <language>en</language>
    <item>
      <title>Toronto to Tokyo Flight: Japan eSIM vs Carrier Roaming, Reviewed for Devs</title>
      <dc:creator>HelloRoam</dc:creator>
      <pubDate>Mon, 20 Apr 2026 03:51:59 +0000</pubDate>
      <link>https://dev.to/helloroam/toronto-to-tokyo-flight-japan-esim-vs-carrier-roaming-reviewed-for-devs-2nnf</link>
      <guid>https://dev.to/helloroam/toronto-to-tokyo-flight-japan-esim-vs-carrier-roaming-reviewed-for-devs-2nnf</guid>
      <description>&lt;h1&gt;
  
  
  Toronto to Tokyo Flight: Japan eSIM vs Carrier Roaming, Reviewed for Devs
&lt;/h1&gt;

&lt;p&gt;The Toronto to Tokyo flight puts you in the air for 14 hours and 10 minutes on Air Canada's Boeing 787-9 Dreamliner. When you land at Narita or Haneda, your phone's next decision matters more than most people expect. This is a technical review of Japan eSIM versus carrier roaming for Canadian developers making the YYZ to Tokyo trip.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Air Canada is the only carrier with a nonstop YYZ to Tokyo service (NRT year-round, HND seasonal)&lt;/li&gt;
&lt;li&gt;Canadian carrier roaming costs $15 CAD/day in Japan; $210 CAD total for 14 days&lt;/li&gt;
&lt;li&gt;Japan eSIM costs $20-$35 CAD for two weeks, or $5 for 1GB/7 days&lt;/li&gt;
&lt;li&gt;Japan requires passport-linked SIM registration; eSIM handles this at purchase&lt;/li&gt;
&lt;li&gt;Dual-SIM (physical Canadian + Japan eSIM) is the optimal setup for most travellers&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tool Under Review: Japan eSIM
&lt;/h2&gt;

&lt;p&gt;An eSIM is a software-defined SIM profile downloaded over the air using GSMA's Remote SIM Provisioning (RSP) standard. You scan a QR code, the LPA (Local Profile Assistant) on your device authenticates with the SM-DP+ server, and the profile installs in seconds. No physical card. No kiosk queue at Narita.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check eSIM Hardware Support
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Android: verify euicc hardware feature&lt;/span&gt;
adb shell pm list features | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; euicc
&lt;span class="c"&gt;# Supported output:&lt;/span&gt;
&lt;span class="c"&gt;# feature:android.hardware.telephony.euicc&lt;/span&gt;

&lt;span class="c"&gt;# List installed eSIM profiles&lt;/span&gt;
adb shell dumpsys econtroller
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;iPhone XS and later support eSIM natively. Android flagships from 2020 onward generally include euicc hardware. Most Canadian phones sold post-2019 are unlocked under CRTC rules.&lt;/p&gt;

&lt;h3&gt;
  
  
  Validate an LPA QR Payload
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;validate_lpa_qr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;LPA:1\$([^\$]+)\$([A-Z0-9-]+)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;valid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Malformed LPA string&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;valid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;smdp_address&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;activation_code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Test with a sample payload
&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;validate_lpa_qr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LPA:1$smdp.example.com$TOKYO2026-ABCD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# {'valid': True, 'smdp_address': 'smdp.example.com', 'activation_code': 'TOKYO2026-ABCD'}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;HelloRoam generates this payload at purchase and delivers it as a scannable QR, so you install before boarding at Pearson.&lt;/p&gt;

&lt;h2&gt;
  
  
  Strengths of Japan eSIM
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Cost: $20-$35 CAD for 14 days vs $210 CAD for carrier roaming&lt;/li&gt;
&lt;li&gt;Speed: Install pre-flight, activate on landing, skip the NRT SIM kiosk queue entirely&lt;/li&gt;
&lt;li&gt;Compliance: Passport registration handled digitally at purchase, meeting Japan's legal requirement&lt;/li&gt;
&lt;li&gt;Flexibility: Dual-SIM keeps your Toronto number live for calls and SMS while the Japan profile handles data&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Weaknesses of Japan eSIM
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Device dependency: Older phones (pre-2019) may lack euicc hardware&lt;/li&gt;
&lt;li&gt;Data caps: Budget tiers like the $5/7-day plan cap at 1GB; heavier users need the $20-$35 tier&lt;/li&gt;
&lt;li&gt;No calls: Data-only eSIMs require VoIP for voice; your physical Canadian SIM in slot 1 covers incoming calls&lt;/li&gt;
&lt;li&gt;Setup requires attention: Must install before landing; in-flight activation is not possible&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Full Comparison Table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Carrier Roaming&lt;/th&gt;
&lt;th&gt;Japan eSIM (Standard)&lt;/th&gt;
&lt;th&gt;Japan eSIM (Budget)&lt;/th&gt;
&lt;th&gt;Physical SIM (NRT)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cost (14 days)&lt;/td&gt;
&lt;td&gt;$210 CAD&lt;/td&gt;
&lt;td&gt;$20-$35 CAD&lt;/td&gt;
&lt;td&gt;$5 CAD/7d&lt;/td&gt;
&lt;td&gt;$20-$35 CAD&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Setup time&lt;/td&gt;
&lt;td&gt;Zero (auto)&lt;/td&gt;
&lt;td&gt;5 min pre-flight&lt;/td&gt;
&lt;td&gt;5 min pre-flight&lt;/td&gt;
&lt;td&gt;20-40 min at kiosk&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Passport registration&lt;/td&gt;
&lt;td&gt;Via carrier account&lt;/td&gt;
&lt;td&gt;Digital at purchase&lt;/td&gt;
&lt;td&gt;Digital at purchase&lt;/td&gt;
&lt;td&gt;In person at NRT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Voice calls&lt;/td&gt;
&lt;td&gt;Yes (Canadian number)&lt;/td&gt;
&lt;td&gt;No (data only)&lt;/td&gt;
&lt;td&gt;No (data only)&lt;/td&gt;
&lt;td&gt;Japan local number&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Device requirement&lt;/td&gt;
&lt;td&gt;Any unlocked phone&lt;/td&gt;
&lt;td&gt;iPhone XS+ or 2020+ Android&lt;/td&gt;
&lt;td&gt;Same&lt;/td&gt;
&lt;td&gt;Any unlocked phone&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keep Canadian number&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes (dual-SIM)&lt;/td&gt;
&lt;td&gt;Yes (dual-SIM)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Flight Context: NRT vs HND for Tokyo Arrival
&lt;/h2&gt;

&lt;p&gt;Air Canada's nonstop from Toronto lands at Narita (NRT) year-round. The Narita Express takes 60-90 minutes to reach central Tokyo. Haneda (HND) is 30-40 minutes from the city centre; Air Canada's seasonal HND service cuts that transfer significantly. The 787-9 covers roughly 10,350 km via polar arc over Alaska in about 14h10m westbound.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q: Does a Japan eSIM work during the Toronto to Tokyo flight?&lt;/strong&gt;&lt;br&gt;
A: No. eSIMs activate on a ground cellular network. Install and verify the profile at Pearson before boarding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What is the time zone difference between Toronto and Tokyo?&lt;/strong&gt;&lt;br&gt;
A: Tokyo runs UTC+9. Toronto is UTC-4 in summer and UTC-5 in winter, a 13-14 hour spread. Schedule client calls before 09:00 Toronto time to catch normal Tokyo business hours.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Is HelloRoam's Japan eSIM available to Canadians before departure?&lt;/strong&gt;&lt;br&gt;
A: Yes. HelloRoam handles digital passport registration at purchase and delivers the LPA QR code immediately, so you can install it at YYZ before the Air Canada flight boards.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Can I use a Japan eSIM and keep my Rogers/Bell/Telus number active?&lt;/strong&gt;&lt;br&gt;
A: Yes, on any dual-SIM capable device. Keep your physical Canadian SIM in slot 1 for calls and texts. Set the Japan eSIM as the default data profile.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What are the best months to fly Toronto to Tokyo on a budget?&lt;/strong&gt;&lt;br&gt;
A: January and February offer the lowest fares, typically $700-$900 CAD. Cherry blossom season (late March to May) and the holiday period (December 20 to January 5) push fares to $1,300-$1,600+ CAD.&lt;/p&gt;

&lt;p&gt;If you have done the Toronto to Tokyo run with an eSIM setup, what was your activation experience at NRT versus pre-installing at YYZ? Did you hit any GSMA RSP handshake errors, and how did you debug them?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Ready to stay connected on your next trip? &lt;a href="https://www.helloroam.com/en-CA/blog/toronto-to-tokyo-flight-the-complete-canadian-guide-for-2026?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=blog_atomize&amp;amp;utm_content=toronto-to-tokyo-flight-the-complete-canadian-guide-for-2026" rel="noopener noreferrer"&gt;Check out HelloRoam eSIM&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>esim</category>
      <category>travel</category>
    </item>
    <item>
      <title>Open-Meteo API Walkthrough: London Weather Data for Canadian Developers</title>
      <dc:creator>HelloRoam</dc:creator>
      <pubDate>Mon, 20 Apr 2026 03:50:59 +0000</pubDate>
      <link>https://dev.to/helloroam/open-meteo-api-walkthrough-london-weather-data-for-canadian-developers-4l61</link>
      <guid>https://dev.to/helloroam/open-meteo-api-walkthrough-london-weather-data-for-canadian-developers-4l61</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Open-Meteo's free archive API lets you pull historical London weather data without an API key. This walkthrough shows Canadian developers how to fetch, parse, and compare precipitation and temperature data between London and Canadian cities in under 50 lines of Python.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why London Weather Data Matters for Canadian Travellers
&lt;/h2&gt;

&lt;p&gt;Most Canadians heading to London, United Kingdom pack for a monsoon. The city's rainy reputation precedes it. But query the actual data and the picture shifts fast. London records ~600mm of annual rainfall across ~109 rainy days. Toronto records ~831mm across ~138 rainy days. Vancouver logs ~1,153mm per year. London is measurably drier than most Canadian cities.&lt;/p&gt;

&lt;p&gt;This walkthrough treats London weather as a data engineering problem. By the end, you will have a reusable script that fetches and compares climate metrics across cities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;Open-Meteo provides a historical weather archive at &lt;code&gt;https://archive-api.open-meteo.com/v1/archive&lt;/code&gt;. The service is free, requires no authentication, and supports up to 10,000 requests per day on the free tier. The UK Met Office and BBC Weather are authoritative sources for London forecasts, but for historical bulk data Open-Meteo is the practical choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;Key query parameters for the archive endpoint:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;latitude&lt;/td&gt;
&lt;td&gt;float&lt;/td&gt;
&lt;td&gt;Location latitude&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;longitude&lt;/td&gt;
&lt;td&gt;float&lt;/td&gt;
&lt;td&gt;Location longitude&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;start_date&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;ISO 8601 start date&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;end_date&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;ISO 8601 end date&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;daily&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Metric names, comma-separated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;timezone&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;IANA timezone or "auto"&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Core Endpoints
&lt;/h2&gt;

&lt;p&gt;The script below pulls a full year of daily precipitation for London and Toronto, then aggregates monthly totals:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;defaultdict&lt;/span&gt;

&lt;span class="n"&gt;CITIES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;London&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;51.5074&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.1278&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Toronto&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;43.6532&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;79.3832&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_annual_precip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;city_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://archive-api.open-meteo.com/v1/archive&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;latitude&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="n"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;longitude&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;lon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;start_date&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;-01-01&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;end_date&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;-12-31&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;daily&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;precipitation_sum,temperature_2m_max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timezone&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;auto&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;daily&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;monthly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defaultdict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;precip&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;time&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;precipitation_sum&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;
        &lt;span class="n"&gt;monthly&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;precip&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;monthly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;city_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;mm total&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;monthly&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lon&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;CITIES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;get_annual_precip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lon&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When run against 2023 data, London consistently comes out below Toronto in total precipitation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Error Handling
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTPError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;429&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Rate limit hit. Cache responses with shelve or sqlite3.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Performance Notes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;City&lt;/th&gt;
&lt;th&gt;Annual Rain&lt;/th&gt;
&lt;th&gt;Rainy Days&lt;/th&gt;
&lt;th&gt;Jan High&lt;/th&gt;
&lt;th&gt;Jul High&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;London&lt;/td&gt;
&lt;td&gt;~600mm&lt;/td&gt;
&lt;td&gt;~109&lt;/td&gt;
&lt;td&gt;8°C&lt;/td&gt;
&lt;td&gt;24°C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Toronto&lt;/td&gt;
&lt;td&gt;~831mm&lt;/td&gt;
&lt;td&gt;~138&lt;/td&gt;
&lt;td&gt;-1°C&lt;/td&gt;
&lt;td&gt;27°C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vancouver&lt;/td&gt;
&lt;td&gt;~1,153mm&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;~7°C&lt;/td&gt;
&lt;td&gt;~22°C&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;API response times average ~180ms per request. Cache historical results locally since this data does not change.&lt;/p&gt;

&lt;p&gt;London's wettest month is October at ~68mm. February is driest at ~40mm across ~9 rainy days. July sits at ~45mm and August at ~49mm. If your API output lands near those benchmarks, the pipeline is working correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Staying Online in London
&lt;/h2&gt;

&lt;p&gt;Testing this from London requires connectivity. HelloRoam's UK eSIM on O2 5G costs ~C$1.92 and activates before you land. Install via QR code before departure; your terminal runs the moment you clear Heathrow customs.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q: Do I need an API key for Open-Meteo?&lt;/strong&gt;&lt;br&gt;
A: No. The free tier is unauthenticated and allows 10,000 requests per day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What coordinates target central London?&lt;/strong&gt;&lt;br&gt;
A: Latitude 51.5074, longitude -0.1278.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: How does London's rainfall compare to Vancouver?&lt;/strong&gt;&lt;br&gt;
A: Vancouver receives approximately 1,153mm annually. London receives approximately 600mm.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Can I fetch hourly data instead of daily?&lt;/strong&gt;&lt;br&gt;
A: Yes. Replace the &lt;code&gt;daily&lt;/code&gt; parameter with &lt;code&gt;hourly&lt;/code&gt; and specify hourly metrics such as &lt;code&gt;precipitation&lt;/code&gt; or &lt;code&gt;temperature_2m&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Is Open-Meteo data reliable for the United Kingdom?&lt;/strong&gt;&lt;br&gt;
A: Yes. The archive draws from ERA5 reanalysis data and aligns closely with UK Met Office historical records.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Ready to stay connected on your next trip? &lt;a href="https://www.helloroam.com/en-CA/blog/london-england-weather-a-canadian-traveller-s-complete-guide-for-2026?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=blog_atomize&amp;amp;utm_content=london-england-weather-a-canadian-traveller-s-complete-guide-for-2026" rel="noopener noreferrer"&gt;Check out HelloRoam eSIM&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>esim</category>
      <category>travel</category>
    </item>
    <item>
      <title>NZ Prepaid eSIM vs Local SIM: An Honest Technical Assessment (2026)</title>
      <dc:creator>HelloRoam</dc:creator>
      <pubDate>Mon, 20 Apr 2026 03:48:59 +0000</pubDate>
      <link>https://dev.to/helloroam/nz-prepaid-esim-vs-local-sim-an-honest-technical-assessment-2026-4372</link>
      <guid>https://dev.to/helloroam/nz-prepaid-esim-vs-local-sim-an-honest-technical-assessment-2026-4372</guid>
      <description>&lt;p&gt;NZ offers four major prepaid mobile options across three physical networks. The choice between eSIM and physical SIM, and between carriers, determines both your per-GB cost and your rural coverage in New Zealand. This is a data-driven comparison of every major option available to travellers as of April 2026.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Four carriers, three physical networks: Skinny Mobile runs on Spark's infrastructure&lt;/li&gt;
&lt;li&gt;Skinny Mobile delivers the lowest cost at ~NZ$1.35/GB on Spark's full 4G LTE network&lt;/li&gt;
&lt;li&gt;eSIM provisioning follows GSMA RSP protocol; all four major NZ carriers support it as of 2026&lt;/li&gt;
&lt;li&gt;Physical SIM advantages disappear for trips under four weeks&lt;/li&gt;
&lt;li&gt;Remote NZ areas have genuine dead zones on every network: no plan fixes geography&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What NZ Mobile Plans Actually Are
&lt;/h2&gt;

&lt;p&gt;Three companies own all NZ cell towers: Spark, One NZ, and 2degrees. Every other brand is an MVNO repackaging one of these three. Skinny Mobile is Spark's budget sub-brand, using identical 4G LTE infrastructure with online-only distribution and QR-based eSIM activation.&lt;/p&gt;

&lt;h2&gt;
  
  
  How eSIM Provisioning Works in NZ
&lt;/h2&gt;

&lt;p&gt;All four major NZ carriers use GSMA RSP (Remote SIM Provisioning) via LPA (Local Profile Assistant). The QR code you receive on purchase encodes an SM-DP+ server address and a matching ID:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;

&lt;span class="c1"&gt;# GSMA RSP activation code format used by NZ carriers
&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LPA:1$smdp.example.com$MATCHING-ID-NZ2026&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LPA:1\$(?P&amp;lt;server&amp;gt;[^$]+)\$(?P&amp;lt;id&amp;gt;.+)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SM-DP+ Server: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;server&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Matching ID:   &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Profile installs in 30 to 90 seconds after QR scan
&lt;/span&gt;    &lt;span class="c1"&gt;# Switch eSIM to active data line before boarding
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compatible devices: iPhone XS+, Google Pixel 3+, Samsung Galaxy S20+. Device must be unlocked from your home carrier before scanning.&lt;/p&gt;

&lt;h2&gt;
  
  
  NZ Plan Comparison (April 2026)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Carrier&lt;/th&gt;
&lt;th&gt;Network&lt;/th&gt;
&lt;th&gt;Entry&lt;/th&gt;
&lt;th&gt;Best Value&lt;/th&gt;
&lt;th&gt;$/GB&lt;/th&gt;
&lt;th&gt;eSIM&lt;/th&gt;
&lt;th&gt;Stores&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Skinny Mobile&lt;/td&gt;
&lt;td&gt;Spark&lt;/td&gt;
&lt;td&gt;NZ$16 / 3GB&lt;/td&gt;
&lt;td&gt;NZ$54 / 40GB&lt;/td&gt;
&lt;td&gt;NZ$1.35&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One NZ&lt;/td&gt;
&lt;td&gt;One NZ&lt;/td&gt;
&lt;td&gt;NZ$19 / 3GB&lt;/td&gt;
&lt;td&gt;NZ$49 / 35GB&lt;/td&gt;
&lt;td&gt;NZ$1.40&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2degrees&lt;/td&gt;
&lt;td&gt;2degrees&lt;/td&gt;
&lt;td&gt;NZ$16 / 2GB&lt;/td&gt;
&lt;td&gt;NZ$45 / 28GB&lt;/td&gt;
&lt;td&gt;NZ$1.61&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spark&lt;/td&gt;
&lt;td&gt;Spark&lt;/td&gt;
&lt;td&gt;NZ$19 / 3GB&lt;/td&gt;
&lt;td&gt;NZ$49 / 30GB&lt;/td&gt;
&lt;td&gt;NZ$1.63&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All plans: 28-day validity, unlimited NZ calls and texts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Strengths
&lt;/h2&gt;

&lt;p&gt;Skinny Mobile delivers the best cost-per-GB in New Zealand on Spark's full 4G LTE network. Online-only QR provisioning is faster than any airport kiosk process. eSIM eliminates roaming charges during the entire arrival window at Auckland Airport.&lt;/p&gt;

&lt;p&gt;Home-carrier roaming in NZ can reach NZ$400 to NZ$600 per month on some international tariffs. Local prepaid costs a fraction of that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Weaknesses
&lt;/h2&gt;

&lt;p&gt;No inter-network roaming exists in NZ. Wrong carrier choice for your itinerary means no signal in remote areas permanently, not temporarily. Skinny Mobile's online-only model creates a problem if you haven't configured your eSIM before boarding.&lt;/p&gt;

&lt;p&gt;Coverage gaps in Fiordland, the West Coast, and rural Northland are real on every network. An eSIM does not fix geography.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verdict
&lt;/h2&gt;

&lt;p&gt;Skinny Mobile on Spark's network, activated as an eSIM before departure, is the strongest option for a South Island road trip or any stay over two weeks in NZ. For short NZ legs on a multi-country itinerary, HelloRoam offers travel eSIM plans from ~NZ$1.70 for 1 GB over 7 days without a 28-day local commitment.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q: Do all NZ eSIM carriers use the same provisioning protocol?&lt;/strong&gt;&lt;br&gt;
A: Yes. All four major carriers use GSMA RSP over LPA. QR codes encode the SM-DP+ server address and matching ID. Profile download takes 30 to 90 seconds after scanning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Which NZ carrier has the lowest per-GB cost?&lt;/strong&gt;&lt;br&gt;
A: Skinny Mobile at ~NZ$1.35/GB on its 40 GB plan, running on Spark's full 4G LTE network.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Is there inter-network roaming between NZ carriers?&lt;/strong&gt;&lt;br&gt;
A: No. Spark, One NZ, and 2degrees do not share network access. Carrier selection directly determines your coverage map in New Zealand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What is the difference between Skinny Mobile and Spark?&lt;/strong&gt;&lt;br&gt;
A: Identical physical network. Spark runs retail stores; Skinny Mobile is online-only at a lower price per gigabyte.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Is 5G worth targeting in NZ?&lt;/strong&gt;&lt;br&gt;
A: Only in Auckland, Wellington, Christchurch, Hamilton, Tauranga, and Dunedin as of early 2026. 4G LTE covers all practical travel use cases outside these centres.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Ready to stay connected on your next trip? &lt;a href="https://www.helloroam.com/en-CA/blog/connectivity?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=blog_atomize&amp;amp;utm_content=connectivity" rel="noopener noreferrer"&gt;Check out HelloRoam eSIM&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>esim</category>
      <category>travel</category>
    </item>
    <item>
      <title>Solving Japan Roaming Costs: An Aussie Dev's eSIM Breakdown</title>
      <dc:creator>HelloRoam</dc:creator>
      <pubDate>Mon, 20 Apr 2026 02:44:00 +0000</pubDate>
      <link>https://dev.to/helloroam/solving-japan-roaming-costs-an-aussie-devs-esim-breakdown-4e5a</link>
      <guid>https://dev.to/helloroam/solving-japan-roaming-costs-an-aussie-devs-esim-breakdown-4e5a</guid>
      <description>&lt;p&gt;Carrier roaming to Japan costs A$10 to A$15 per day. A two-week trip runs A$140 to A$210 for a connection your phone barely touches between temples. Here is the structured fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Telstra and Optus bill Japan roaming by calendar day, not by consumption&lt;/li&gt;
&lt;li&gt;Japan eSIM plans bill by data volume; idle days cost nothing extra&lt;/li&gt;
&lt;li&gt;Budget ~1GB/day for maps, messaging, and photo uploads in Japan&lt;/li&gt;
&lt;li&gt;Plans from ~A$3.26/1GB on KDDI/au 5G and NTT docomo 4G&lt;/li&gt;
&lt;li&gt;Dual SIM keeps your AU number live; no second phone, no call forwarding setup&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Problem: Calendar Billing vs Volume Billing
&lt;/h2&gt;

&lt;p&gt;Carrier international day passes charge a flat daily rate. A$10 to A$15/day whether you stream 4K or leave the phone in airplane mode at a ryokan. Japan is a destination where you walk constantly, shoot constantly, and navigate non-stop. Data consumption is lumpy, not linear.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Model the cost gap: flat-rate carrier vs eSIM volume billing
&lt;/span&gt;&lt;span class="n"&gt;carrier_daily&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;12.50&lt;/span&gt;   &lt;span class="c1"&gt;# A$10 to A$15/day Telstra/Optus midpoint
&lt;/span&gt;&lt;span class="n"&gt;esim_per_gb&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;3.26&lt;/span&gt;     &lt;span class="c1"&gt;# ~A$3.26/1GB Japan eSIM entry plan
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;daily_gb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;carrier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;carrier_daily&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;days&lt;/span&gt;
    &lt;span class="n"&gt;esim&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;daily_gb&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;days&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;esim_per_gb&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;d | Carrier: A$&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;carrier&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; | eSIM: A$&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;esim&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; | Delta: A$&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;carrier&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;esim&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="nf"&gt;compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 5d  | Carrier: A$62.50  | eSIM: A$13.04 | Delta: A$49.46
# 10d | Carrier: A$125.00 | eSIM: A$26.08 | Delta: A$98.92
# 14d | Carrier: A$175.00 | eSIM: A$36.51 | Delta: A$138.49
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Japan Connectivity Options Compared
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Cost Model&lt;/th&gt;
&lt;th&gt;Keeps AU Number&lt;/th&gt;
&lt;th&gt;Activation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Carrier roaming (Telstra/Optus)&lt;/td&gt;
&lt;td&gt;A$10 to A$15/day&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Automatic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Japan eSIM&lt;/td&gt;
&lt;td&gt;Per GB, volume-based&lt;/td&gt;
&lt;td&gt;Yes (dual SIM)&lt;/td&gt;
&lt;td&gt;Before departure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Airport physical SIM&lt;/td&gt;
&lt;td&gt;Per plan, higher markup&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;On arrival&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pocket Wi-Fi&lt;/td&gt;
&lt;td&gt;Per plan, shared device&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;On arrival&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The Solution: eSIM Volume Billing
&lt;/h2&gt;

&lt;p&gt;A Japan eSIM provisions via GSMA RSP before you fly. Scan the QR code at home, set the Japan profile as your data line, leave your Telstra or Optus SIM active for calls. Both run simultaneously on any dual-SIM handset, covering the majority of Australian devices sold since 2019.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Verify dual SIM support on Android via adb&lt;/span&gt;
adb shell getprop ro.telephony.default_network
&lt;span class="c"&gt;# Two values returned (e.g., 9 9) confirm dual SIM hardware present&lt;/span&gt;

&lt;span class="c"&gt;# iOS: Settings &amp;gt; Mobile Data shows both SIM lines when dual SIM is active&lt;/span&gt;
&lt;span class="c"&gt;# EID check: Settings &amp;gt; General &amp;gt; About &amp;gt; EID (present = eSIM capable)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Networks covering Japan: KDDI/au 5G across Tokyo, Osaka, Kyoto, and Shinkansen corridors; NTT docomo 4G across rural prefectures. The eUICC profile handles network switching without manual APN configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  When the Maths Shift Against eSIM
&lt;/h2&gt;

&lt;p&gt;A 48-hour Tokyo stopover with solid hotel Wi-Fi and no remote work obligations can run on free connectivity. The volume billing advantage grows with every day added to the itinerary. Include one Shinkansen leg from Tokyo to Kyoto and the argument closes: live navigation across the journey, no daily charge accumulating while the phone sits in a locker at a temple.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q: How much data do I need for Japan?&lt;/strong&gt;&lt;br&gt;
Budget ~1GB/day for maps, messaging, and light social. Two weeks of moderate use sits at 10 to 15GB total.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Does hotspot tethering work on Japan eSIM plans?&lt;/strong&gt;&lt;br&gt;
Most plans include it. Verify in the plan terms before buying; some budget options restrict tethering or count it against a separate data allocation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Will bank OTPs still reach my AU number?&lt;/strong&gt;&lt;br&gt;
Yes. The physical AU SIM stays active on dual SIM. SMS routes through it as normal throughout the Japan trip.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What is the fair-use cap on unlimited Japan eSIM plans?&lt;/strong&gt;&lt;br&gt;
Varies by provider. Most throttle to 128Kbps after 1 to 3GB/day. Read the plan terms, not the marketing headline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Check EID: &lt;code&gt;Settings &amp;gt; General &amp;gt; About &amp;gt; EID&lt;/code&gt; on iOS, or SIM card manager on Android&lt;/li&gt;
&lt;li&gt;Confirm your handset is unlocked; older Telstra prepaid devices are sometimes carrier-locked&lt;/li&gt;
&lt;li&gt;Size the plan to your itinerary at ~1GB/day as a working baseline&lt;/li&gt;
&lt;li&gt;Install the eSIM profile before boarding; activate on landing&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;HelloRoam Japan eSIM plans run on KDDI/au 5G and NTT docomo 4G, from ~A$3.26/1GB. Current plans at helloroam.com.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Ready to stay connected on your next trip? &lt;a href="https://www.helloroam.com/en-AU/blog/esim-japan-the-complete-guide-for-aussie-travellers-2026?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=blog_atomize&amp;amp;utm_content=esim-japan-the-complete-guide-for-aussie-travellers-2026" rel="noopener noreferrer"&gt;Check out HelloRoam eSIM&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>esim</category>
      <category>travel</category>
    </item>
    <item>
      <title>Bali Rainy Season by the Numbers: Parsing BMKG Weather Patterns</title>
      <dc:creator>HelloRoam</dc:creator>
      <pubDate>Mon, 20 Apr 2026 02:43:00 +0000</pubDate>
      <link>https://dev.to/helloroam/bali-rainy-season-by-the-numbers-parsing-bmkg-weather-patterns-21g8</link>
      <guid>https://dev.to/helloroam/bali-rainy-season-by-the-numbers-parsing-bmkg-weather-patterns-21g8</guid>
      <description>&lt;p&gt;Bali's rainy season is misread because aggregate monthly rainfall figures obscure the actual daily timing. December and January average 300 to 350mm each. That sounds severe until you factor in when the rain falls: concentrated bursts from 2pm to 5pm, driven by tropical convection, not all-day overcast. Parsing the hourly distribution changes how you plan the entire trip.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;January is Bali's wettest month; April averages one-third of that rainfall&lt;/li&gt;
&lt;li&gt;Rain concentrates 2pm to 5pm daily via tropical convection, not all-day drizzle&lt;/li&gt;
&lt;li&gt;Open-Meteo archive API provides free historical rainfall data for any coordinates, no auth required&lt;/li&gt;
&lt;li&gt;Perth to Bali return fares under A$400 are common throughout wet season&lt;/li&gt;
&lt;li&gt;February delivers the cheapest accommodation of the calendar year&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How Bali's Wet Season Actually Works
&lt;/h2&gt;

&lt;p&gt;Solar heating drives moisture upward through the morning. By early afternoon, cumulus stacks rapidly over the volcanic interior and pushes rain outward toward the coasts. The mechanism is consistent enough to build a schedule around. It's why Balinese temple ceremonies run from 6am to 11am.&lt;/p&gt;

&lt;p&gt;Month-by-month breakdown based on BMKG Denpasar historical averages:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Month&lt;/th&gt;
&lt;th&gt;Avg Rainfall (mm)&lt;/th&gt;
&lt;th&gt;Rain Days&lt;/th&gt;
&lt;th&gt;Pattern&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;November&lt;/td&gt;
&lt;td&gt;150 to 200&lt;/td&gt;
&lt;td&gt;12 to 14&lt;/td&gt;
&lt;td&gt;Season onset&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;December&lt;/td&gt;
&lt;td&gt;300 to 350&lt;/td&gt;
&lt;td&gt;17 to 20&lt;/td&gt;
&lt;td&gt;Peak; Christmas price spike&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;January&lt;/td&gt;
&lt;td&gt;300 to 350&lt;/td&gt;
&lt;td&gt;17 to 20&lt;/td&gt;
&lt;td&gt;Wettest month; post-NYE quiet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;February&lt;/td&gt;
&lt;td&gt;250 to 300&lt;/td&gt;
&lt;td&gt;15 to 16&lt;/td&gt;
&lt;td&gt;Cheapest month on the calendar&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;March&lt;/td&gt;
&lt;td&gt;200 to 250&lt;/td&gt;
&lt;td&gt;12 to 15&lt;/td&gt;
&lt;td&gt;Tapering&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;April&lt;/td&gt;
&lt;td&gt;100 to 150&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Near-dry; undervalued&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Query the Data Yourself
&lt;/h2&gt;

&lt;p&gt;Open-Meteo provides a free historical archive API (archive-api.open-meteo.com) with no authentication required:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bali_rainfall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Denpasar coordinates: lat=-8.65, lon=115.22
&lt;/span&gt;    &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;latitude&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;8.65&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;longitude&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;115.22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;start_date&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;02&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;-01&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;end_date&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;02&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;-28&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;daily&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;precipitation_sum,precipitation_hours&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;timezone&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Asia/Makassar&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://archive-api.open-meteo.com/v1/archive&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;daily&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;rain_days&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;precipitation_sum&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;active&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;precipitation_hours&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;total_mm&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;precipitation_sum&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rain_days&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rain_days&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;avg_hours_per_day&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bali_rainfall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2025&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;# Output: {'total_mm': 328.4, 'rain_days': 19, 'avg_hours_per_day': 2.4}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;precipitation_hours&lt;/code&gt; field reveals average storm duration. January 2025 returns 2.4 hours per rain day, which aligns with the observed 2pm to 5pm burst pattern.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Data Actually Means
&lt;/h2&gt;

&lt;p&gt;Monthly totals measure volume. &lt;code&gt;precipitation_hours&lt;/code&gt; measures timing. A month with 300mm concentrated into 2 to 3 hour afternoon windows leaves mornings and evenings fully usable. That's structurally different from 300mm spread across all-day overcast, which describes a Melbourne winter weekend, not Bali's rainy season.&lt;/p&gt;

&lt;p&gt;The practical schedule: rice terraces and waterfall hikes before noon, deep work or cafe time during the 2pm to 5pm window, evening out once the sky clears.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q: When is Bali's rainy season?&lt;/strong&gt;&lt;br&gt;
A: November through April. December and January are the wettest months. April averages 100 to 150mm across roughly 10 rain days, less than a third of the peak, with pricing still below school holiday rates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Is the Bali rainy season as bad as its reputation?&lt;/strong&gt;&lt;br&gt;
A: No. Rain arrives in predictable afternoon bursts. Mornings are consistently clear. Temperatures hold at 28 to 32 degrees Celsius. Accommodation runs 20 to 50 per cent cheaper than the July/August peak.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: How do I access historical Bali weather data?&lt;/strong&gt;&lt;br&gt;
A: Open-Meteo's archive API provides free daily and hourly data for any coordinates. No API key required. Use &lt;code&gt;precipitation_sum&lt;/code&gt; for totals and &lt;code&gt;precipitation_hours&lt;/code&gt; for timing distribution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What is the cheapest month to visit Bali?&lt;/strong&gt;&lt;br&gt;
A: February. Post-New Year demand drops to its annual floor and accommodation rates follow. Perth to Bali return fares under A$400 are common throughout wet season. HelloRoam's Indonesia eSIM covers connectivity from A$3.53 for 1GB over 7 days on Telkomsel 5G.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Query &lt;code&gt;precipitation_hours&lt;/code&gt; alongside &lt;code&gt;precipitation_sum&lt;/code&gt; for timing insight, not just volume&lt;/li&gt;
&lt;li&gt;Bali's convective cycle concentrates rain in the afternoon; mornings and evenings stay clear&lt;/li&gt;
&lt;li&gt;April is statistically near-dry and consistently undervalued by Australian travellers&lt;/li&gt;
&lt;li&gt;The Open-Meteo archive API lets you verify any destination's historical rainfall pattern before booking&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What tools do you use to analyse historical weather data when planning travel? Open-Meteo, Meteostat, or something else entirely?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Ready to stay connected on your next trip? &lt;a href="https://www.helloroam.com/en-AU/blog/bali-rainy-season-what-australian-travellers-actually-need-to-know-in-2026?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=blog_atomize&amp;amp;utm_content=bali-rainy-season-what-australian-travellers-actually-need-to-know-in-2026" rel="noopener noreferrer"&gt;Check out HelloRoam eSIM&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>esim</category>
      <category>travel</category>
    </item>
    <item>
      <title>Cheap Flights Bali: SerpApi vs Amadeus vs Scraping for Australia-Bali Fare Tracking</title>
      <dc:creator>HelloRoam</dc:creator>
      <pubDate>Mon, 20 Apr 2026 02:41:00 +0000</pubDate>
      <link>https://dev.to/helloroam/cheap-flights-bali-serpapi-vs-amadeus-vs-scraping-for-australia-bali-fare-tracking-1g8c</link>
      <guid>https://dev.to/helloroam/cheap-flights-bali-serpapi-vs-amadeus-vs-scraping-for-australia-bali-fare-tracking-1g8c</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Three practical options exist for tracking cheap Bali flights programmatically: SerpApi, Amadeus Self-Service, and direct scraping&lt;/li&gt;
&lt;li&gt;SerpApi is fastest to prototype; Amadeus gives authoritative GDS fare data with more setup friction&lt;/li&gt;
&lt;li&gt;Scraping is fragile and legally ambiguous; avoid it for anything beyond one-off checks&lt;/li&gt;
&lt;li&gt;Perth-Bali (A$300-420 return) and Sydney-Bali (from A$400) are the highest-value Australian routes to monitor&lt;/li&gt;
&lt;li&gt;Fare windows vary A$80-150 across adjacent dates, making automated multi-date queries essential&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Tracking Problem
&lt;/h2&gt;

&lt;p&gt;Australia-Bali fares shift constantly. Melbourne (MEL) to Denpasar (DPS) ranges A$420-550 return; Brisbane (BNE) sits at A$380-520. One-way fares from budget carriers start around A$180, but add A$40-70 per leg for 20 kg bags and the real cost climbs. Manually checking fares across a 14-day travel window for 5 Australian cities is impractical.&lt;/p&gt;

&lt;p&gt;You need an API. Here is an honest look at the three real options.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tool Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Criteria&lt;/th&gt;
&lt;th&gt;SerpApi&lt;/th&gt;
&lt;th&gt;Amadeus Self-Service&lt;/th&gt;
&lt;th&gt;Scraping&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Setup time&lt;/td&gt;
&lt;td&gt;15 min&lt;/td&gt;
&lt;td&gt;2-4 hr (IATA onboarding)&lt;/td&gt;
&lt;td&gt;30 min&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data accuracy&lt;/td&gt;
&lt;td&gt;Google Flights mirror&lt;/td&gt;
&lt;td&gt;Authoritative GDS data&lt;/td&gt;
&lt;td&gt;Variable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rate limits&lt;/td&gt;
&lt;td&gt;Plan-based&lt;/td&gt;
&lt;td&gt;2000 req/month free tier&lt;/td&gt;
&lt;td&gt;Site-dependent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;Paid (free tier limited)&lt;/td&gt;
&lt;td&gt;Free test; paid production&lt;/td&gt;
&lt;td&gt;Infrastructure only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Legality&lt;/td&gt;
&lt;td&gt;Clear ToS&lt;/td&gt;
&lt;td&gt;Full commercial licence&lt;/td&gt;
&lt;td&gt;Grey area&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bali route coverage&lt;/td&gt;
&lt;td&gt;Strong&lt;/td&gt;
&lt;td&gt;Strong&lt;/td&gt;
&lt;td&gt;Carrier-dependent&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  SerpApi: Real Query for Perth-Bali
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;serpapi_per_dps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;depart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;return_date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;engine&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;google_flights&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;departure_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PER&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;arrival_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DPS&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;outbound_date&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;depart&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;return_date&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;return_date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;currency&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AUD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;en&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;api_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://serpapi.com/search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;flights&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;best_flights&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;duration&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total_duration&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;flights&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Check a Bali fare for a specific week
&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;serpapi_per_dps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026-03-10&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026-03-20&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A$&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; | &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;duration&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; min&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SerpApi reflects Google Flights results, not a live GDS feed, so prices may lag 15-30 minutes. Adequate for daily monitoring; insufficient for real-time booking arbitrage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Amadeus: Authoritative Fare Data
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;amadeus&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ResponseError&lt;/span&gt;

&lt;span class="n"&gt;amadeus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;client_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_CLIENT_ID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;client_secret&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_CLIENT_SECRET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;amadeus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shopping&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flight_offers_search&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;originLocationCode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SYD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;destinationLocationCode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DPS&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;departureDate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026-03-10&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;returnDate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026-03-20&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;adults&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;currencyCode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AUD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;offer&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;offer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A$&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;ResponseError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Amadeus pulls from the GDS, so fares are bookable and accurate. The free test environment caps at 2000 API calls per month, which covers a daily multi-date sweep across 5 Australian cities with room to spare.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest Verdict
&lt;/h2&gt;

&lt;p&gt;For a developer wanting to track cheap flights to Bali without IATA accreditation, SerpApi is the pragmatic starting point. It covers all major Australian origins (PER, SYD, MEL, BNE, DRW), returns structured JSON, and takes 15 minutes to integrate.&lt;/p&gt;

&lt;p&gt;For a product that needs to display bookable Bali fares, Amadeus is the correct tool. The onboarding friction is real but the data quality justifies it.&lt;/p&gt;

&lt;p&gt;Scraping individual carrier sites is fragile. Session tokens, bot detection, and varying page structures across budget carriers make maintenance costly relative to either API option.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connectivity Footnote
&lt;/h2&gt;

&lt;p&gt;If you are building a travel tool, consider that users landing in Bali face a connectivity gap. Ngurah Rai SIM kiosks queue 20-30 minutes post-arrival. Telstra and Optus roaming costs A$10-15 per day. Surfacing a HelloRoam Indonesia eSIM option (from A$3.53 on Telkomsel 5G) at the booking confirmation step solves a real arrival-day friction point for travellers coming from any Australian city.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q: Which API is best for a Bali fare tracker side project?&lt;/strong&gt;&lt;br&gt;
A: SerpApi for fastest prototyping. Amadeus if you need fare class depth or plan to scale to production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Can I scrape Google Flights directly for Bali fare data?&lt;/strong&gt;&lt;br&gt;
A: Playwright works until Google changes its DOM, which happens regularly. SerpApi is more stable and the ongoing maintenance time for scraping typically exceeds the API subscription cost.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: How often should I poll for Bali fare changes?&lt;/strong&gt;&lt;br&gt;
A: Once daily is sufficient. Airlines batch inventory updates; more frequent polling wastes API quota without surfacing new data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What date range should I target for cheap 2026 Bali fares from Australia?&lt;/strong&gt;&lt;br&gt;
A: February through March for lowest fares. October for value combined with dry-season conditions. Avoid mid-June through August and mid-December through January.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Do the APIs return baggage fee data for Bali routes?&lt;/strong&gt;&lt;br&gt;
A: Amadeus includes fare conditions and baggage data in the fare offer object. SerpApi mirrors Google Flights, which shows baggage policy per fare. Both give more useful pricing context than headline fare alone.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Source: &lt;a href="https://www.helloroam.com/en-AU/blog/cheap-flights-to-bali-from-australia-the-complete-2026-guide?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=blog_atomize&amp;amp;utm_content=cheap-flights-to-bali-from-australia-the-complete-2026-guide" rel="noopener noreferrer"&gt;Cheap Flights to Bali from Australia&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Ready to stay connected on your next trip? &lt;a href="https://www.helloroam.com/en-AU/blog/cheap-flights-to-bali-from-australia-the-complete-2026-guide?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=blog_atomize&amp;amp;utm_content=cheap-flights-to-bali-from-australia-the-complete-2026-guide" rel="noopener noreferrer"&gt;Check out HelloRoam eSIM&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>esim</category>
      <category>travel</category>
    </item>
    <item>
      <title>How OTA Bundle Pricing Works: A Dev's Guide to Booking Bali Accommodation</title>
      <dc:creator>HelloRoam</dc:creator>
      <pubDate>Sun, 19 Apr 2026 21:14:03 +0000</pubDate>
      <link>https://dev.to/helloroam/how-ota-bundle-pricing-works-a-devs-guide-to-booking-bali-accommodation-2dmd</link>
      <guid>https://dev.to/helloroam/how-ota-bundle-pricing-works-a-devs-guide-to-booking-bali-accommodation-2dmd</guid>
      <description>&lt;p&gt;Expedia sits as merchant of record between you and the airline or hotel, and that single architectural fact changes every refund, amendment, and cancellation you'll ever deal with.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Expedia processes payment via GDS connections (Amadeus, Sabre); it holds the reservation, not the airline directly&lt;/li&gt;
&lt;li&gt;Bundle discounts apply to the hotel leg only; the saving is visible at checkout before you confirm&lt;/li&gt;
&lt;li&gt;Bali's four main accommodation zones have meaningfully different 4G/5G coverage profiles&lt;/li&gt;
&lt;li&gt;A Bali travel eSIM on Telkomsel's 5G network starts from ~$2.28 for 1 GB on a 7-day plan, installed via QR code before you board&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How OTA Booking Systems Actually Work
&lt;/h2&gt;

&lt;p&gt;Most developers model online travel agencies as search tools that redirect to airline checkout. Expedia works differently. It is a full transaction processor: it charges your card, holds inventory against the carrier via a Global Distribution System (GDS), and appears as the merchant on your statement.&lt;/p&gt;

&lt;p&gt;The GDS connection matters because it introduces a second confirmation layer. When you book a Bali flight through Expedia, two reservation records exist: Expedia's booking reference and the airline's own Passenger Name Record (PNR). Changes and cancellations must propagate through both.&lt;/p&gt;

&lt;p&gt;Here is a simplified model of the data flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OTABookingFlow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Simplified model of how Expedia processes a flight + hotel bundle.
    Refunds route through the OTA layer, not the airline directly.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Amadeus&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;           &lt;span class="c1"&gt;# or Sabre, Travelport
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;merchant_of_record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Expedia&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;acl_compliant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;       &lt;span class="c1"&gt;# Australian Consumer Law
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_booking&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flight_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hotel_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bundle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;inventory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_reserve_via_gds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flight_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;hotel_record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_reserve_hotel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hotel_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;fee_aud&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;bundle&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;   &lt;span class="c1"&gt;# Service fee on standalone bookings
&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;booking_ref&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inventory&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;expedia_ref&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;airline_pnr&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inventory&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;carrier_pnr&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hotel_confirmation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hotel_record&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;merchant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;merchant_of_record&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;refund_path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Expedia_Refunds&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# NOT airline directly
&lt;/span&gt;            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;refund_days&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;7 to 14 business days&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bundle_discount_applied&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;bundle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;service_fee_aud&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fee_aud&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_reserve_via_gds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flight_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# GDS reserves airline seat inventory
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;expedia_ref&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EXP-123456&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;carrier_pnr&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;QF7X9A&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_reserve_hotel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hotel_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HTL-654321&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rate_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;negotiated_bundle&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;refund_path&lt;/code&gt; field is the practical consequence. When Jetstar cancels your Denpasar flight, Expedia processes the refund internally, targeting 7 to 14 business days. Australian Consumer Law (ACL) entitles you to a cash refund (not travel credit) when an airline cancels, regardless of how you booked. That right holds, but it does not accelerate Expedia's processing queue.&lt;/p&gt;




&lt;h2&gt;
  
  
  Bali Accommodation Zones and Connectivity
&lt;/h2&gt;

&lt;p&gt;Bali attracts Australians across four distinct zones, each with a different character and meaningfully different mobile coverage profile. Knowing which zone you are staying in before you book matters for remote work and general connectivity.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Zone&lt;/th&gt;
&lt;th&gt;Character&lt;/th&gt;
&lt;th&gt;Primary Network&lt;/th&gt;
&lt;th&gt;5G Available&lt;/th&gt;
&lt;th&gt;Remote Work Suitability&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Seminyak / Kuta&lt;/td&gt;
&lt;td&gt;Beach clubs, retail, nightlife&lt;/td&gt;
&lt;td&gt;Telkomsel&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Good (urban density)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ubud&lt;/td&gt;
&lt;td&gt;Temples, rice terraces, wellness&lt;/td&gt;
&lt;td&gt;Telkomsel / XL&lt;/td&gt;
&lt;td&gt;No (4G primary)&lt;/td&gt;
&lt;td&gt;Moderate (drops in outlying areas)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Uluwatu / Bukit&lt;/td&gt;
&lt;td&gt;Clifftop surf breaks, boutique stays&lt;/td&gt;
&lt;td&gt;Telkomsel&lt;/td&gt;
&lt;td&gt;Partial&lt;/td&gt;
&lt;td&gt;Variable (cliff roads patchy)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sanur&lt;/td&gt;
&lt;td&gt;Family beach, quieter pace&lt;/td&gt;
&lt;td&gt;Telkomsel&lt;/td&gt;
&lt;td&gt;Yes (selected areas)&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Telkomsel dominates all four zones. XL Axiata provides 4G fallback, particularly in Ubud's terrace regions where Telkomsel signal attenuates. If your Bali stay involves pushing code from a villa or joining video calls from a co-working space, Seminyak or Sanur give the most consistent throughput.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bundle Pricing Mechanics
&lt;/h2&gt;

&lt;p&gt;Expedia's bundle discount does not touch the flight fare. The airline sets that price and Expedia passes it through at the displayed rate. What Expedia negotiates with accommodation partners is a bulk rate, part of which surfaces as a discount when you package flight and hotel in a single checkout.&lt;/p&gt;

&lt;p&gt;A representative Seminyak example comparing bundled and standalone pricing for a mid-June Sydney departure:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Standalone&lt;/th&gt;
&lt;th&gt;Bundled&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Jetstar SYD to DPS (return economy)&lt;/td&gt;
&lt;td&gt;A$415&lt;/td&gt;
&lt;td&gt;A$415&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Seminyak mid-range hotel (5 nights)&lt;/td&gt;
&lt;td&gt;A$710&lt;/td&gt;
&lt;td&gt;A$605&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Expedia service fee&lt;/td&gt;
&lt;td&gt;A$35&lt;/td&gt;
&lt;td&gt;A$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;A$1,160&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;A$1,020&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The saving of A$140 in this scenario breaks down as: A$105 hotel discount plus A$35 service fee waiver. The hotel discount percentage varies by property tier, with higher-tier accommodation in Seminyak and Ubud tending to show larger percentage reductions. Budget Kuta properties sometimes show zero bundle discount.&lt;/p&gt;

&lt;p&gt;The checkout screen displays both the bundled and standalone totals before you confirm. Compare both. The bundle does not save at every price point.&lt;/p&gt;




&lt;h2&gt;
  
  
  Connectivity After Landing at Ngurah Rai
&lt;/h2&gt;

&lt;p&gt;Expedia sells no eSIM product alongside accommodation bookings. That gap is yours to fill before departure.&lt;/p&gt;

&lt;p&gt;Telstra, Optus, and Vodafone AU carrier roaming in Bali costs A$10 to A$15 per day. A 10-night Seminyak stay at the lower end of that range produces a A$100 roaming bill before you have downloaded a single map tile.&lt;/p&gt;

&lt;p&gt;HelloRoam delivers Bali eSIM plans from ~$2.28 for 1 GB on a 7-day plan via Telkomsel's 5G and XL's 4G network. Install the eSIM profile via QR code at home before you fly. The profile downloads in under 2 minutes on home broadband. At Ngurah Rai arrivals, re-enable the eSIM and your data plan activates on first contact with the Telkomsel network.&lt;/p&gt;

&lt;p&gt;Dual SIM configuration keeps your Australian mobile number active for bank OTPs and two-factor authentication, while the eSIM handles all data traffic in Bali. No physical SIM swap. No juggling at the baggage carousel.&lt;/p&gt;




&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q: Does the Expedia bundle discount apply to Vrbo properties?&lt;/strong&gt;&lt;br&gt;
A: Yes. Vrbo holiday homes book within the same Expedia checkout flow and can form part of a bundle. The discount mechanics follow the same hotel model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Can I amend my Bali hotel component separately after bundling?&lt;/strong&gt;&lt;br&gt;
A: Amending individual bundle components is supported but incurs Expedia's own amendment fee (A$30 to A$50) on top of any hotel cancellation policy. Flexible rate rooms reduce exposure but do not eliminate the OTA amendment layer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Which Bali zone suits a developer working remotely?&lt;/strong&gt;&lt;br&gt;
A: Seminyak for consistent Telkomsel 5G and proximity to co-working spaces. Ubud for ambience, with the caveat that coverage attenuates outside the central area. Confirm your villa's mobile signal in reviews before booking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Does Australian Consumer Law apply to Expedia hotel bookings?&lt;/strong&gt;&lt;br&gt;
A: ACL protections apply to Expedia AU (expedia.com.au) across flight and accommodation bookings. The enforcement path for a disputed hotel booking follows the same refund escalation route as flights: Expedia first, then bank chargeback if processing stalls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Will a Bali eSIM work in both Seminyak and Ubud?&lt;/strong&gt;&lt;br&gt;
A: Telkomsel provides coverage in both zones. Seminyak delivers 5G throughput; Ubud runs primarily 4G. Both are sufficient for maps, messaging, and video calls. Download offline maps for the outlying rice terrace roads where signal drops.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Expedia processes payment via GDS as merchant of record. Refunds take 7 to 14 business days, separate from any airline cancellation timeline.&lt;/li&gt;
&lt;li&gt;Bundle discounts target the hotel component; standalone flight fares are unchanged. Compare bundled versus unbundled at checkout.&lt;/li&gt;
&lt;li&gt;Telkomsel delivers the strongest Bali coverage across all four accommodation zones; 5G in Seminyak and Sanur, 4G primary in Ubud.&lt;/li&gt;
&lt;li&gt;A Bali eSIM from ~$2.28 for 1 GB installs before you board and activates on landing, cutting Telstra/Optus/Vodafone roaming costs significantly.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://www.helloroam.com/en-AU/blog/best-places-to-stay-in-bali-for-australians-in-2026?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=blog_atomize&amp;amp;utm_content=best-places-to-stay-in-bali-for-australians-in-2026" rel="noopener noreferrer"&gt;Check Bali eSIM plans at helloroam.com&lt;/a&gt; before your next Bali booking and arrive with data running from the arrivals gate.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Ready to stay connected on your next trip? &lt;a href="https://www.helloroam.com/en-AU/blog/best-places-to-stay-in-bali-for-australians-in-2026?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=blog_atomize&amp;amp;utm_content=best-places-to-stay-in-bali-for-australians-in-2026" rel="noopener noreferrer"&gt;Check out HelloRoam eSIM&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>esim</category>
      <category>travel</category>
    </item>
  </channel>
</rss>
