RORK LABJP
TOOLING — Rork's developer repos keep moving: rork-xcode was updated on July 16, rork-device on July 15, and rork-plist on July 13OPUS46 — Claude Opus 4.6 is live in Rork, and Rork Max is built to assemble apps on top of Claude CodeSIM — A cloud iOS simulator runs in the browser, with one click to install on a device and two clicks to publish to the App StoreMAX — Rork Max emits pure Swift rather than React Native, reaching iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and even iMessageNATIVE — That opens up HealthKit, ARKit and LiDAR, NFC, Dynamic Island, Live Activities, 3D through Metal, and on-device inference with Core MLSEED — Rork raised a $15M seed led by Left Lane Capital, with Peak XV and a16z Speedrun joining the roundTOOLING — Rork's developer repos keep moving: rork-xcode was updated on July 16, rork-device on July 15, and rork-plist on July 13OPUS46 — Claude Opus 4.6 is live in Rork, and Rork Max is built to assemble apps on top of Claude CodeSIM — A cloud iOS simulator runs in the browser, with one click to install on a device and two clicks to publish to the App StoreMAX — Rork Max emits pure Swift rather than React Native, reaching iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and even iMessageNATIVE — That opens up HealthKit, ARKit and LiDAR, NFC, Dynamic Island, Live Activities, 3D through Metal, and on-device inference with Core MLSEED — Rork raised a $15M seed led by Left Lane Capital, with Peak XV and a16z Speedrun joining the round
Articles/Dev Tools
Dev Tools/2026-05-10Intermediate

Why Your Rork iOS App's API Calls Fail Silently — Fixing App Transport Security the Right Way

When a Rork-built iOS app's API requests fail with no error and no log, App Transport Security (ATS) is almost always the culprit. Here is the minimum-privilege fix and an Info.plist that actually passes review.

Rork515iOS109App Transport SecurityATSNetwork3Troubleshooting38

"It worked perfectly in the simulator, but the moment I shipped it to TestFlight, the API calls just stopped — no error, no crash, nothing." I have lived this exact scenario. Around the time my indie app portfolio crossed 50 million cumulative downloads, I swapped out the measurement SDK for an ad network, and on launch day the app stayed silent: it never crashed, the spinner never stopped, the response simply never arrived. After three days of customer support tickets piling up, I traced the cause back to App Transport Security (ATS) quietly blocking HTTP traffic at the OS level.

This silent failure is especially painful in the Rork + EAS pipeline. Coming from web development, it feels reasonable to hit http://api.example.com directly. But on a release build the OS swallows the request before your JavaScript ever sees it, and even your try / catch blocks never fire. Below is the order in which I triage these incidents, plus an Info.plist that lets you grant the smallest possible exception while still passing Apple's review.

Why does it fail "silently"? ATS defaults explained

Since iOS 9, ATS enforces all of the following on every iOS app by default:

  • Connections must use HTTPS
  • TLS must be 1.2 or higher
  • The full certificate chain must validate
  • The cipher suite must support Forward Secrecy

Any traffic that violates these rules gets killed by the OS. fetch and axios are both backed by URLSession, so once the OS drops the request, your JavaScript layer often does not even receive an error object. You can wrap the call in try / catch all day long; if the connection never leaves the device, catch never fires.

There is a saying I inherited from my grandfathers, who were both temple carpenters in Japan: "If your first plane stroke is crooked, every later step inherits the warp." When the foundation of the network stack is wrong, the bug is invisible from any layer above.

Triage order — work from the bottom up

Without a clean error message, you cannot guess your way through Info.plist changes. You first need to nail down what the network is actually doing. Here is the order I follow on real incidents.

1. URL scheme and port

# Sweep every API string in your project
grep -rE 'https?://[^"]+' src/ app/ services/ 2>/dev/null | grep -v '\.test\.'

If even one URL starts with http://, that is almost certainly your problem. The same applies to localhost if you are testing the Expo Dev Client against a real device — ATS exceptions are required.

2. Measure the TLS version and cipher suite

The URL might be HTTPS while the server's TLS configuration is too old to satisfy ATS. Confirm from a Mac terminal:

# Check that the server actually negotiates TLS 1.2
openssl s_client -connect api.example.com:443 -tls1_2 < /dev/null
 
# List the cipher suites the server offers (requires nmap)
nmap --script ssl-enum-ciphers -p 443 api.example.com

If you see Cipher is (NONE) or handshake failure, the server fails ATS's cipher requirements. No amount of Info.plist editing on the Rork side will save you — fix the server, or move to a different domain.

3. Confirm the exception actually shipped

Inspect the final Info.plist inside the build that EAS produced.

# Pull Info.plist from a TestFlight IPA
unzip -p "App.ipa" "Payload/*.app/Info.plist" | plutil -convert xml1 -o - -

Look for the NSAppTransportSecurity key and verify its content is what you expect. With Rork projects, app.config.ts changes occasionally fail to propagate because of EAS caching, so this final check matters.

Writing a minimum-privilege ATS exception

This is the substance of the fix. Setting NSAllowsArbitraryLoads = true is not just a review risk — it actively exposes your users to MITM attacks. As an indie developer who wants the apps my children eventually inherit to be honest pieces of work, this is a line I will not cross casually. Apple's review team rejects builds that flip the global flag without a documented justification.

Pattern A: allow HTTP for one specific domain

Use this when a single legacy API or payment partner cannot serve HTTPS yet.

<!-- Info.plist (injected via app.config.ts ios.infoPlist) -->
<key>NSAppTransportSecurity</key>
<dict>
  <key>NSExceptionDomains</key>
  <dict>
    <key>legacy-api.example.com</key>
    <dict>
      <!-- Allow HTTP traffic -->
      <key>NSExceptionAllowsInsecureHTTPLoads</key>
      <true/>
      <!-- Lower the TLS floor for this domain only (optional) -->
      <key>NSExceptionMinimumTLSVersion</key>
      <string>TLSv1.0</string>
      <!-- Set true only when you also need subdomains -->
      <key>NSIncludesSubdomains</key>
      <false/>
    </dict>
  </dict>
</dict>

In Rork, you typically inject this from app.config.ts:

// app.config.ts
export default {
  expo: {
    ios: {
      infoPlist: {
        NSAppTransportSecurity: {
          NSExceptionDomains: {
            "legacy-api.example.com": {
              NSExceptionAllowsInsecureHTTPLoads: true,
              NSExceptionMinimumTLSVersion: "TLSv1.0",
              NSIncludesSubdomains: false,
            },
          },
        },
      },
    },
  },
};

Expected output: after expo prebuild, the generated ios/<App>/Info.plist should contain the same keys, verbatim.

Pattern B: relax media traffic only

If you are progressively downloading m3u8 / HLS streams, NSAllowsArbitraryLoadsInMedia exempts video traffic without touching your API surface. From experience with AdMob video ads, this exception has dramatically smaller side effects than the global one.

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSAllowsArbitraryLoadsInMedia</key>
  <true/>
</dict>

Pattern C: relax WebView only

When the app itself talks HTTPS but you embed a WebView that loads external HTTP resources:

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSAllowsArbitraryLoadsInWebContent</key>
  <true/>
</dict>

This lets <img src="http://..."> and similar subresources load inside the WebView without opening the rest of the app to insecure connections.

Avoiding rejection at App Review

Apple's review team will ask why a build sets NSAllowsArbitraryLoads = true. Since the privacy manifest became mandatory, in my experience reviewers also look at ATS settings more often (I covered the privacy manifest side at Fixing privacy manifest API declaration errors during Rork app review).

Justifications that tend to work:

  • Communication with a third-party legacy server you do not control (bonus points if you can show a migration timeline)
  • Public infrastructure such as some regional broadcasting APIs that simply do not offer HTTPS
  • A test server inside a closed network whose CA cannot be trusted by the device (must be disabled in production builds)

"We need it for video playback" is rarely accepted on its own — reviewers will usually push you toward the narrower NSAllowsArbitraryLoadsInMedia instead.

A small probe you can paste in

Here is a tiny utility I keep around to verify that the ATS exception actually took effect on a real device. It pokes both HTTPS and HTTP endpoints so you can see which side URLSession is killing.

// utils/atsProbe.ts
// Hit HTTPS and HTTP back to back to surface which side is being blocked
export async function atsProbe() {
  const targets = [
    { label: "HTTPS", url: "https://httpbin.org/get" },
    { label: "HTTP",  url: "http://httpbin.org/get"  },
  ];
  for (const t of targets) {
    const t0 = Date.now();
    try {
      const res = await fetch(t.url, { method: "GET" });
      console.log(`[ATS Probe] ${t.label} ok=${res.ok} status=${res.status} ms=${Date.now() - t0}`);
    } catch (e: any) {
      // When ATS blocks the call, the error message is usually "Network request failed"
      console.log(`[ATS Probe] ${t.label} threw: ${e?.message ?? e} ms=${Date.now() - t0}`);
    }
  }
}

Expected behaviour:

  • No exception in place: HTTPS succeeds, HTTP throws Network request failed
  • Pattern A with httpbin.org whitelisted: both succeed
  • Pattern B (media only): the HTTP fetch still fails, which is the correct outcome

If "HTTPS works but HTTP fails," ATS is doing its job and you can scope your fix narrowly. If even the HTTPS call dies, the cause is somewhere else — proxy, DNS, or certificate pinning — and you should switch to a more general triage like Debugging network and API requests in Rork apps.

Operational rules I follow on shipped apps

Closing notes from running ATS exceptions on a portfolio that crossed 50 million cumulative downloads:

  • New apps start with no NSAllowsArbitraryLoads. With Cloudflare, Supabase, or any modern backend, HTTPS is enough on day one.
  • When an exception is introduced for legacy compatibility, both the release notes and the internal README must record the exempted domain and a removal target date.
  • Every six months I run an inventory pass and forcibly retire exceptions that are still in place but no longer needed.
  • After a server migration or CDN switch, re-run the TLS measurement the next day. The configuration drift is real.

ATS issues are loud when they hit production but cheap to prevent — a few lines of config and fifteen minutes of testing. If you also want to map the layer above this one, Triaging database backend connection errors in Rork iOS apps gives you a complementary view of the network stack.

Thank you for reading this through.

Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Dev Tools2026-05-29
Diagnosing 'Network request failed' That Only Hits Android Emulator in Rork
Your fetch returns fine in the iOS simulator but throws 'Network request failed' the moment you switch to Android. Here is the diagnosis order I use to separate localhost, cleartext, certificate, and proxy issues, with code that actually compiles.
Dev Tools2026-05-21
Rork iOS App Rejected with ITMS-90683 on TestFlight — How to Fix Missing Purpose Strings via app.json
If your Rork-built iOS app passes upload but gets an email titled ITMS-90683: Missing Purpose String in Info.plist, this guide walks through the real cause and the permanent fix via app.json, based on 12 years of shipping personal iOS apps with the same problem appearing across new SDK updates.
Dev Tools2026-05-18
Fixing iOS-Only Linking.canOpenURL False Returns in Rork — The LSApplicationQueriesSchemes Trap
Production iOS builds silently route every user to the mobile web instead of opening TikTok or X? This is almost always a missing LSApplicationQueriesSchemes entry. Here is the full fix path for Rork.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →