guides

In-app browser cookies, explained (the engineering view)

the linkboo team·8 min read·updated Mon Jun 01 2026 17:00:00 GMT-0700 (Pacific Daylight Time)
On this page

scope

Why a webview embedded in a third-party app does not share cookies with the system browser, what that means in iOS and Android terms specifically, and the consequences for any web flow that depends on persistent authentication. The consumer-facing version of this problem is on the thesis page; this is the engineering breakdown that subordinates to it.

A cookie jar is the persistence layer for HTTP cookies, scoped to a browser instance. On iOS, the system Safari instance writes to a jar managed by WebKit and persisted at app-bundle paths under Safari's container. On Android, Chrome writes to a jar managed by the Chromium network stack, persisted under Chrome's app data directory. Each is process-bound and accessible only to the owning application via system-mediated APIs.

Webviews embedded in other apps are different processes. They run as part of the host app (TikTok, Instagram, Threads, Messenger). They have their own cookie storage, scoped to their own app sandbox, not shared with Safari or Chrome.

This isolation is the iOS and Android security model functioning correctly. The cost is that legitimate sessions don't propagate.

iOS: WKWebView vs SFSafariViewController vs ASWebAuthenticationSession

iOS offers three primary mechanisms for showing web content inside another app. Their cookie behavior differs.

WKWebView

  • Default rendering surface for in-app browsers in third-party apps.
  • Cookies stored in WKHTTPCookieStore, scoped to the WKWebsiteDataStore instance.
  • Default WKWebsiteDataStore is persistent and shared across all WKWebView instances within the same app, but not shared with Safari.
  • WKWebsiteDataStore.default() is the persistent store; WKWebsiteDataStore.nonPersistent() is in-memory.
  • TikTok, Instagram, Threads, Messenger, Snapchat, LinkedIn, Twitter/X — all use WKWebView for their in-app browsers.
  • A site loaded in TikTok's WKWebView cannot read cookies written by Safari, full stop. No API exists to bridge them.

SFSafariViewController

  • Apple-provided embedded Safari view. Used less frequently in social apps because it doesn't allow the host app to customize chrome.
  • Cookies are shared with Safari. This is the explicit difference vs WKWebView.
  • From the destination site's perspective, SFSafariViewController looks like Safari and acts like Safari.
  • If apps used SFSafariViewController instead of WKWebView, the cookie-isolation problem would not exist. They don't, because WKWebView is more customizable.

ASWebAuthenticationSession

  • Purpose-built for OAuth flows. Shares cookies with Safari for the duration of the auth session.
  • Used by apps that want to surface a "Sign in with Google" or "Sign in with Apple" flow that respects the user's existing Safari session.
  • Not what social apps use for general link-tapping.

The architectural decision that produces the cookie-jar problem: social apps choose WKWebView (customizable, isolated) over SFSafariViewController (uncustomizable, integrated). The choice is rational from the app's perspective and adversarial from the destination site's perspective.

Android: WebView vs Chrome Custom Tabs

Symmetric structure on Android.

WebView (or android.webkit.WebView)

  • Default rendering surface for in-app browsers on Android.
  • Cookies stored in CookieManager, scoped to the host app's WebView instance.
  • No sharing with Chrome's cookies. Same security model as iOS — webviews don't read system-browser data.
  • TikTok, Instagram, Facebook, Messenger, Snapchat all use customized WebView (most based on the Chromium WebView shipped via Google Play Services).

Chrome Custom Tabs

  • Google-provided embedded Chrome view.
  • Shares cookies with Chrome. Custom Tabs are essentially Chrome rendering chrome-less inside another app, with the calling app able to specify some UI options (toolbar color, action button).
  • A site loaded in Chrome Custom Tabs has access to the user's Chrome session.
  • If apps used Custom Tabs instead of WebView, the cookie-isolation problem would not exist on Android. They don't, for the same customization reasons.

The choice is the same as on iOS: social apps prefer the customizable, isolated rendering surface. Cookie isolation is the side effect.

what gets isolated, specifically

Concretely, here is what does not transfer between Safari/Chrome and a third-party app's webview:

  • Cookie headers for any domain
  • localStorage and sessionStorage entries (per-origin, per-context)
  • IndexedDB stores
  • Service worker registrations and their cached responses
  • WebSQL databases (deprecated but still present in some webviews)
  • Permissions grants (notification, camera, geolocation) per-origin
  • Saved form data and credentials managed by the system password manager
  • Cached HTTP responses, image cache, font cache
  • TLS session keys and HSTS preferences for some configurations

Sites that depend on any of the above for session continuity will degrade in an in-app browser. The set is large enough that "most authenticated flows" is a fair description of the affected surface.

consequences for common auth patterns

Auth pattern Behavior in WKWebView / Android WebView
First-party cookie session (e.g., set by destination on previous Safari visit) Not available — separate jar
Third-party cookie session (e.g., ad-tracker, embedded analytics) Often blocked entirely by ITP/equivalents, plus separate jar
OAuth via window.open pop-up Pop-up frequently suppressed by host webview; auth flow breaks
OAuth via redirect Works mechanically but completes in the isolated jar — session ends when webview closes
Sign in with Apple (ASWebAuthenticationSession) Works only if destination integrates the SDK; not the default surface
Magic-link via email Works if user follows link in mail app and lands in Safari; breaks if mail-app link routes back to in-app webview
Passkeys / WebAuthn Inconsistent — some webviews surface platform authenticator, some don't
Apple Pay (PaymentRequest API) Requires access to device payment keychain; webviews don't have it; button doesn't render
Google Pay (PaymentRequest API) Same as Apple Pay on Android
Stripe Checkout Renders but may degrade — Apple Pay / Google Pay buttons missing, autofill broken
Saved card autofill Requires system password-manager integration; webview can't request it

The pattern: anything that depends on the system-level user identity (cookies, payments, biometrics, passwords) is gated behind the system browser. Webviews are second-class citizens for authenticated flows by design.

detection

To detect that page execution is happening inside a third-party in-app browser, inspect navigator.userAgent. The UA string carries identifying signatures appended by the host app.

function detectInAppBrowser() {
  const ua = navigator.userAgent || '';
  return {
    tiktok: /BytedanceWebview|musical_ly|com\.zhiliaoapp\.musically|com\.ss\.android\.ugc\.trill/i.test(ua),
    instagram: /Instagram/i.test(ua),
    facebook: /FBAN|FBAV|FB_IAB/i.test(ua),
    messenger: /FB_IAB\/Messenger|Messenger/i.test(ua),
    threads: /Barcelona|Threads/i.test(ua),
    snapchat: /Snapchat/i.test(ua),
    linkedin: /LinkedInApp/i.test(ua),
    twitter: /Twitter|TwitterAndroid/i.test(ua),
    pinterest: /Pinterest/i.test(ua),
  };
}

Caveat: UA strings change with app releases. Pattern maintenance is required. The full regex set, including edge cases and platform variants, is in the dev-reference page /guides/detect-tiktok-in-app-browser-useragent. That page is the pair to this one — cookies explainer here, UA detection there.

escape mechanisms

If detection succeeds, the goal is to hand the visitor off to their device's real browser — closing the isolated webview and reopening the destination in Safari or Chrome so the user's real cookies and logged-in session come with them.

iOS

iOS provides private URL schemes that, when fired from a webview, cause the OS to dispatch the URL to Safari instead of handling it within the host app. The calling webview closes, Safari opens, and the user's Safari session is intact. Some iOS versions and host-app configurations suppress these schemes, so a reliable escape flow includes fallback handling — typically a user-visible "Open in Safari" prompt that is far more discoverable than the host app's buried menu option.

Android

Android's intent system lets a webview pass a URL to the system for routing outside the current app. A well-formed intent URL can target the user's default browser directly, with a fallback URL for devices where the target browser is not installed. The host webview hands the intent to Android, which routes it to the system browser, and the user's Chrome session is intact.

How linkboo handles this

linkboo's escape flow detects that the click came from inside an in-app browser and hands the visitor off to their device's real browser automatically. On the rare device where the automatic hand-off can't fire, linkboo shows a clean one-tap escape — far more discoverable than the platform's buried menu. The viewer taps your bio link, the destination opens, they're already logged in. They didn't know an escape happened. This is the gap linkboo's escape flow bridges in production.

structural implications for app developers

If you ship a mobile app that includes an in-app browser, the cookie isolation is a feature of the platform, not a flag you can toggle. You can choose:

  1. WKWebView / Android WebView — customizable, isolated cookie jar. Default for social apps.
  2. SFSafariViewController / Chrome Custom Tabs — uncustomizable, shares cookies with system browser. Reasonable for apps that want destinations to behave normally.
  3. Hand off to system browserUIApplication.shared.open(_:) on iOS, Intent.ACTION_VIEW on Android. Most respectful of the user's session continuity. Largest UX departure from "stay inside our app."

Social apps overwhelmingly choose option 1. Tools like linkboo exist because the consequences fall on creators and destination sites, not on the social platform that made the choice.

structural implications for destination sites

If you operate a destination that depends on authenticated sessions and you see traffic from social platforms, you should:

  1. Detect in-app webviews via UA. Use the patterns linked above.
  2. Either degrade gracefully or bounce out. Degrading means: render a UA-specific page that explains the session is unavailable in this browser, with a one-tap "Open in browser" affordance. Bouncing out means: hand the visitor off to their real browser immediately on page load, before rendering.
  3. Don't rely on third-party cookies. ITP/equivalents and the cookie-jar isolation compound; third-party cookies are not viable for any destination served via in-app webview.
  4. Don't rely on window.open for OAuth. Use ASWebAuthenticationSession-equivalent SDK flows on native, or full-page redirects on web.

If you're building an escape flow yourself and want a maintained, hosted version with the detection patterns kept current and the iOS-version edge cases handled, linkboo wraps all of the above into a single link. See plans →.

references

  • Apple WKWebView documentation, WKWebsiteDataStore cookie storage semantics
  • Apple SFSafariViewController cookie-sharing behavior
  • Apple ASWebAuthenticationSession for OAuth
  • Android WebView and CookieManager documentation
  • Android Chrome Custom Tabs integration guide
  • W3C Storage Access API (limited adoption in webviews)
  • Apple ITP technical disclosures (cookie partitioning, third-party cookie blocking)

Stop losing the click after the tap.

linkboo escapes the in-app browser so your real page loads — fast.

Start for free →