Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Instagram

Avatar for Ziad Ziad
November 05, 2026

 Instagram

RE of the app

Avatar for Ziad

Ziad

November 05, 2026

Other Decks in Programming

Transcript

  1. INSTAGRAM FOR ANDROID 454.0.0.54.77 · META-SIGNED I N D E

    P E N D E N T S TAT I C T E A R D O W N W H AT T H E P R O D U C T I O N A P P I S W I R E D TO C O L L E C T Your phone is the questionnaire. Your thumb fills it in. A read of the decompiled Instagram Android client. Not a leak, not a live capture — just what the code itself declares: the feature vectors it builds, the on-device models it runs, and the server flags that switch them on. Separated, throughout, into verified, inferred, and not proven. 190 7d 23 31 session feature fields (ranking_session_*) app-open history retained on device AI / automation apps probed by name classes decompiled for behaviour logic STATIC ANALYSIS · JADX + DEX STRINGS NO ACCOUNT · NO NETWORK CAPTURE · SERVER FLAGS APPLY
  2. 01 — METHOD & SCOPE What this is, and what

    it cannot say. Everything here comes from static analysis of one APK: decompiled Java (jadx) and the raw string/asset corpus. That means I can read the capability wired into the client — class names, field names, GraphQL queries, config gates, on-device schemas. It does not mean I watched any of it run or leave the device. Field names are evidence of intent, not proof of transmission. T H E A RT I FA C T THE CORPUS package com.instagram.android zip entries 11,112 version 454.0.0.54.77 · code 386014758 dex files 30 min / target SDK 28 / 37 unique dex strings 747,673 (deduped, string-table) size 149,372,203 bytes class descriptors 224,279 signature Scheme v3 + v3.1 · verified assets 3,151 (1,790 text-like) apk sha-256 255374e88793f2cf50001b088821ee3856 9c9dc5d080294f839542920783d371 permissions declared 82 S TAT I C A N A LY S I S C A N P R O V E S TAT I C A N A LY S I S C A N N OT P R O V E · A class / code path exists and what it references. · Exact field, event, and column names. · That a field is actually sent, or how often. · What Meta's servers do with it. · Which server flag (MobileConfig id) gates a path. · On-device schemas & retention (e.g. Room, MLDW). · Whether a flag is on for your account. · The behaviour of models downloaded after install. · Declared permissions and <queries>. · Anything requiring a live run or packet capture. A U T H E N T I C I T Y — I N D E P E N D E N T LY V E R I F I E D SIGNATURE SCHEME V3 / V3.1 OK The APK verifies under a signing lineage (key rotation), which fixes it as the genuine, unmodified app: SDK 33+ signer O=Meta Platforms Inc., Menlo Park CA · cert 3a10c50c…c014 SDK 24–32 signer CN=Kevin Systrom, O=Instagram Inc, San Francisco · cert 5f3e50f4…e305 The legacy certificate is Instagram's original founder signing key, carried forward in the lineage. Version 454.0.0.54.77 is newer than the builds on public APK mirrors at time of analysis. Hash, signature, permissions and version re-derived here with sha256, apksigner and aapt; strings parsed from the DEX string tables directly. CONFIDENCE LEGEND USED THROUGHOUT INFERRED 01 · METHOD & SCOPE reasonable from evidence VERIFIED NOT PROVEN code / string / schema present HIGH multiple corroborating signals plausible, unconfirmed IG 454.0.0.54.77 · STATIC TEARDOWN
  3. 02 — THE SHAPE OF IT Not one creepy feature.

    An architecture. The headline isn't any single signal — it's how they fit together. The client continuously turns device state and fine-grained interaction into dense feature vectors, feeds them to on-device models, syncs server-computed personalization features back down, and ties it all to a cross-app identity. Almost every piece is switched by a remote flag, so the installed app is not frozen — behaviour changes without an update. WHEN HOW WHAT Casper Session vector Carrera + taxonomy An on-device model that predicts when you'll open the app next, from up to 7 190 fields built live while you scroll — attention, hesitation, rejection, device Inferred interests, topic taxonomies, and embeddings. The server infers; the client days of open/close history and device state. Timing, not taste. context. The inputs to feed & ad ranking. displays, pins, and lets you "tune" them. T H E P L U M B I N G U N D E R N E AT H Identity Ad ledger Image scores Re-engage FDID · PhoneID · US-DID injected into requests; read from the Facebook app. On-device journal of ad taps, CTAs, inapp-browser events, x-outs. SigLIP2 on-device embedder + perphoto content scores. Background prefetch, FBNS push, boottime rescheduling. Capability ≠ activation. I found explicit MobileConfig gates on Casper, the AI-apps scan, the personalization fetch, and READ THIS FIRST contact upload — and the AI-apps scan only runs when its analytics event is sampled. So "the app can do X" is accurate; "the app always does X to everyone" is not something this teardown shows. 02 · THE SHAPE OF IT WHEN · HOW · WHAT + PLUMBING
  4. 03 — SYSTEM ONE · TIMING HIGH CONFIDENCE Casper forecasts

    your next open. com.meta.casper.Casper and com.instagram.casper.IgSignalsCasper implement an on-device predictor of the next app open. It is gated: IgSignalsCasper.A00() returns null unless a MobileConfig flag (36317865497863129) is set. When active it builds a feature vector and runs a downloaded model. // IgSignalsCasper.A01() — cleaned // asset: ig4a_meta_casper_mldw_ir.json long now = clock.invoke(); { feature.storageFreeMb = freeBytes / 1024 / 1024; "name": "ig_app_start_dataset", Calendar c = Calendar.getInstance(TimeZone.getDefault()); "retentionInSec": 604800, c.setTime(new Date(now)); "columns": ["dense_features", feature.dayOfWeek = c.get(Calendar.DAY_OF_WEEK); "split", feature.hourOfDay = c.get(Calendar.HOUR_OF_DAY); "timestamp_ms"] feature.minute = c.get(Calendar.MINUTE); // + open/close counts & durations over // 7 days } // event: ig_app_start_event // 1h,2h,6h,12h,1d,2d,5d,7d windows // + 5 recent app-start offsets, network, // power-save; fused with server features FIRES ON (TRIGGER ENUM) Feature build is local, timezone-aware, and combines device_feature_count with server_feature_count. on_background on_foreground on_background_fetch on_background_app_start Not just "on close" — foreground and background-fetch too. RUNTIME DELIVERY T H E N W H AT ExecuTorch (org.pytorch.executorch.*). Runs on Voltron (OdinExecutorchVoltronLoader, IgMetaCasperBgFetchService, CPU/NPU, in short bursts around lifecycle events — not a loop. files/meta_casper). The APK can ship a preload; FBNS / local notifications → re- descriptor; weights download later. BackgroundPrefetchJobService → engage. LINKAGE INFERRED Read: it isn't reading your mind — it's pattern-matching your routine. The forecast ("likely back ~11pm, low battery") is itself the product: it decides when the app should get ready and when to nudge you. 03 · CASPER EXECUTORCH + VOLTRON · 7-DAY MLDW STORE
  5. 0 4 — S Y S T E M T

    W O · AT T E N T I O N FIELD NAMES VERIFIED 190 ways to measure a scroll. Live during a session the client assembles 190 distinct ranking_session_* fields (parsed straight from the DEX string tables). I read and categorised all of them — not vague analytics, but named inputs to feed and ad ranking. 100 · recency timers (time_since) 90 · counters, flags & device state A clean split: 100 time_since_* timers + 90 counters/flags/readings = 190. Cut a different way, 61 of the 190 are ad-related and 24 carry _incl_sleep — they keep counting while the phone is asleep. AT T E N T I O N REJECTION DEVICE CONTEXT max_scroll_depth_current_surface num_ad_xouts battery_level_pct scroll_reversal_count num_ad_negative_signals low_power_mode_flag num_gestures num_ad_unlikes thermal_state video_dwell_time_sum unengaged_surface_exit_after_ad_co unt audio_output_route video_dwell_time_max is_plugged_in output_volume_level time_since_last_xout_repetitive video_pause_count is_system_dark_mode is_peak_hour S I G N A L → I N F E R E N C E → A C T I O N ( I L L U S T R AT I V E ; M E C H A N I S M I N F E R R E D ) scroll_reversal_count ↑ you went back for more → topic interest → more like it num_ad_xouts ↑ explicit rejection → ad fatigue → fewer of that ad battery_level_pct ↓ + late hour short session likely → lighter batch, cheaper prefetch Every pause is a vote. Every scroll-back is a louder one. 04 · SESSION VECTOR 190 FIELDS · 100 TIMERS · 24 INCL_SLEEP · 61 AD
  6. 05 — THE QUIET FIELDS VERIFIED STRINGS The ones that

    don't feel like data. Buried in the 190 are fields most people would never guess are ranking inputs. Two clusters stood out to me. I N - A P P B ROW S E R , D OW N TO T H E AU TO F I L L T I M E R S T H AT S U R V I V E S L E E P When an ad opens Instagram's in-app browser, the client tracks 24 fields end in _incl_sleep: recency that keeps counting even recency of very specific events: while the device is idle, so "how long since you last reacted" persists across the night. time_since_last_ad_iab_contact_autofill time_since_last_ad_xout_incl_sleep time_since_last_ad_iab_contact_payment_autofill time_since_last_organic_like_incl_sleep time_since_last_ad_iab_navigation time_since_last_ad_click_incl_sleep time_since_last_ad_iab_no_bounce time_since_last_main_surface_incl_sleep time_since_last_ad_iab_offapp_exit Autofilling contact or payment details in the in-app browser is a named recency signal — a strong purchase-intent marker. " L A S T S E S S I O N " I S A N I N P U T TO T H E N E X T O N E p13n_last_session_duration_ms p13n_last_session_end_time_ms p13n_last_session_ad_impression_count p13n_last_session_max_scroll_depth p13n_last_session_did_like_post p13n_last_session_did_open_comments The next session doesn't start blank. It opens knowing how you left: how long you stayed, how far you got, how many ads you saw, whether you liked anything, whether you opened the comments. It remembers the last time you almost cared. 05 · THE QUIET FIELDS IAB AUTOFILL · INCL_SLEEP · LAST-SESSION P13N
  7. 06 — SYSTEM THREE · INTEREST CLIENT VERIFIED · SERVER

    INFERRED How a thumb becomes a profile. Content carries topic / taxonomy labels; your behaviour attaches you to them; the result is an interest profile Instagram now lets you see and "tune." The internal name across these strings is Carrera. The inference is server-side; the client fetches, displays, pins, and edits it. THE PIPELINE content taxonomy your actions → → affinity / embedding C A R R E R A — I N T E R E S T CO N T R O L S U R FA C E → inferred interests topics_v9 arg_inferred_interests_list contextual_rec_embedding_v9 interest_ids_to_keep pinned_carrera_interests TUNE_YOUR_ALGO_INTEREST_KEYWORD CARRERA_ALGORITHM_CONTROL_CENTER The client can fetch an inferred-interest list, pin interests to the profile, remove them, and reset preferences. feed · Explore · ads TO P I C S & E M B E D D I N G S CarreraPopulateInferredInterestsMutation matched_taxonomy_interest → subtopics_v9 embedding_v9 adtaxon_i18n_top1_l7_prediction ranking_info_recommender_type Versioned topic/ad taxonomies and recommendation embeddings. The heavy inference runs on Meta's servers; the names are what the client references. W H Y I T M AT T E R S The app never needs to know why you paused. It only needs to know the pause landed on a post tagged "fitness," "travel," or "drama." Enough pauses become an interest; enough interests become a profile — built from behaviour, with nothing typed. 06 · CARRERA / INTEREST CLIENT-SIDE CONTROL · SERVER-SIDE INFERENCE
  8. 07 — THE BRIDGE FETCH / PARSE / STORE VERIFIED

    Server features, stored on the phone. PersonalizationFetcher is the concrete seam between Meta's servers and the on-device store. It fetches numeric features over GraphQL and writes them into a local ODML "p13n" Room database for on-device use — a different layer from Casper (timing) and Carrera (interest). // PersonalizationFetcher.A00 / A01 — cleaned request = GraphQL("IGAdsPersonalizationMetadataQuery", root = "xig_ads_personalization_features", test_mode = MobileConfig(36323217027187286)); for (feature in response) { store.put(feature_id, new Feature(FeatureType.DOUBLE, value, feature_id)); log("use_case_id", "use_case_version", "feature_id", "feature_value", ttlMinutes); } log("feature_count", store.size()); // failures: FAILURE_NULL_PERSONALIZATION_FEATURES, // FAILURE_FEATURE_ID_CONFLICT, ... W H AT L A N D S L O C A L LY WHY IT'S INTERESTING Typed Feature values (DOUBLE / BOOLEAN / LONG), each with a use_case_id, version, and a TTL in minutes — written to Personalization isn't only "phone → server." The server can push feature values down, where on-device models read them — so com.instagram.odml.p13n.room.*. ranking state lives on both sides. INFERRED Which feature IDs drive which decision, and whether every account receives this set, are not visible statically. 07 · PERSONALIZATIONFETCHER GRAPHQL → ODML P13N ROOM STORE
  9. 0 8 — T H E I N S TA

    L L P R O B E CODE PATH VERIFIED It checks which AI apps you have. A dedicated routine iterates a curated enum of 23 AI / automation apps, calls PackageManager.getPackageInfo() for each, and logs the ones present into an installed_apps field. It is not a scan of every app on your phone — it's a named list, declared in the manifest's <queries>. T H E 2 3 P R O B E D PA C K A G E S ( E N U M E N U M C 2 4 4 6 3 0 9 J S ) ChatGPT Gemini Youware Emergent Claude Copilot a0.dev Tasker Perplexity IFTTT Character.AI Zapier Replika MacroDroid Poe Automate Pi NotebookLM Home Assistant Manus Notion Replit Airtable // AiAppsDetectorRunner — cleaned if (MobileConfig(36329874226438827)) { // gate last = prefs("ig_ai_apps_detector_prefs").get("last_detection_time"); if (now - last >= intervalHours(24)) { // default 24h event = logger("odin_ai_apps_detector"); if (event.isSampled()) { // <-- only if sampled for (pkg in AI_APPS_ENUM) present[pkg] = pm.getPackageInfo(pkg) != null; event.set("installed_apps", present.keys()); event.emit(); prefs.put("last_detection_time", now); } } } G AT E D T H ROT T L E D SAMPLED MobileConfig flag must be on. At most once / 24h per device. Only when the event is sampled. Read: "which AI tools does this person use?" is a sharp profiling and competitive-intelligence signal — note how many of the 23 are automation apps (Tasker, IFTTT, Zapier, MacroDroid, Automate). But the honest scope is: a curated presence check, remotely gated, throttled, and sampled — not a silent inventory of everything installed. 08 · AI-APPS DETECTOR 23 PACKAGES · INSTALLED_APPS · GATED + SAMPLED
  10. 09 — THE MODEL ZOO NAMES VERIFIED · ACTIVATION GATED

    Casper is not the only model. Casper sits in a family of on-device models (ODML). Some predict app entry; some decide what to prefetch; some score ads. One string even distinguishes PREDICT from PREDICT_AND_TRAIN — i.e. on-device training, not just inference. Names below are verified; which are active depends on server flags. App Entry Ads Prefetch Predicts app-entry behaviour from session history. Predicts which ads are worth loading early. odml_app_entry_model_android odml_ads_prefetch_model Ad Swipe / Scroll Story Prefetch Swipe-up & scroll-speed behaviour on Reels/Stories ads. Which stories to prefetch. odml_swipe_up StoryPrefetchODML IG_ADS_ODML_SCROLLING_SPEED Share-sheet ranking Abandonment Ranks who you're most likely to share with; labels & can upload examples. Estimates a feed-abandonment probability. ShareSheetRankingMlEngineWrapper abandon_model_probability_ppm ON-DEVICE TRAINING IS IN THE VOCABUL ARY IG_ADS_ODML_PREDICT IG_ADS_ODML_PREDICT_AND_TRAIN AppEntryOdmlManager.onUserLeftSurface IG_ADS_ODML_FEATURES_AGGREGATION IG_ADS_ODML_PYTORCH_DOWNLOAD SessionHistoryFeatureSource Also present: NER, language-model biasing, speech recognition, voice-activity detection, and AR segmentation modules — mostly camera / messaging / accessibility, not feed profiling. Read: because models ship via Voltron/ExecuTorch after install, the set of active models drifts over time. "How many AI models are in Instagram?" has no fixed answer — which is exactly why round numbers like "31 models" should be treated with suspicion. 09 · ODML MODEL ZOO PREDICT + TRAIN · DELIVERED POST-INSTALL
  11. 1 0 — I M A G E U N

    D E R S TA N D I N G ON-DEVICE VERIFIED · UPLOAD NOT PROVEN Your camera roll, indexed into numbers. This operates on your device camera roll — the photos stored on your phone, read through Android's MediaStore — not content you've already posted. The query, scores and LOCAL GALLERY — NOT YOUR POSTS scanner_versions column all belong to a local index of gallery media, and the surrounding strings are all camera-roll / media-picker (ALLOW/DENY_ACCESS_TO_DEVICE_CAMERA_ROLL, CAMERA_ROLL_INSPIRATION_*). When you grant gallery access (the create/post flow needs it), an on-device scanner turns accessible photos into vectors and scores via Siglip2OnDeviceImageEmbedder, and stores them locally — including reverse-geocoded location read from each photo's EXIF. // actual on-device query — gallery_media_metadata SELECT id, scanner_versions, feature_name, locality, sub_admin_area, country_name, // geo from photo EXIF visual_embeddings, person_score, food_score, nature_score, landmark_score, aesthetic_score, blur_score, document_score, pet_score, date_sec FROM gallery_media_metadata; SCOPE IS BOUNDED BY THE PERMISSION YOU GRANT On Android 14+, READ_MEDIA_VISUAL_USER_SELECTED limits it to photos you pick; full READ_MEDIA_IMAGES exposes the whole roll. ACCESS_MEDIA_LOCATION is what unlocks the per-photo geo-tags. PIPELINE STRINGS Siglip2OnDeviceImageEmbedder on_device_embedding_generation_start/end onDeviceImageLabelCreateLogEvent request_has_on_device_embeddings NOT PROVEN That embeddings, scores or geo-tags are transmitted off-device. On-device generation is verified; egress is not. request_has_on_device_embeddings hints embeddings can accompany a request, but that's not confirmation they do. 10 · IMAGE UNDERSTANDING LOCAL CAMERA ROLL · SCORES + GEO · EGRESS UNCONFIRMED
  12. 11 — IDENTITY HIGH CONFIDENCE One device, one cross-app identity.

    A set of identifiers ties the install to the wider Meta family. The most concrete piece: UsdidRequestInterceptor, a native-backed interceptor (usdidinterceptor) that injects a US-DID token into outgoing requests, and UsdidValuesProvider, which reads that value from the Facebook app via a shared content provider. IDENTIFIERS & PLUMBING FDID PhoneID US-DID AsyncInstagramPhoneIdProvider CrossSigningService A D AT T R I B U T I O N FEO2 AdvertisingIdClient / AD_ID UsdidRequestInterceptor FamilyAppsUserValuesProvider ACCESS_ADSERVICES_ATTRIBUTION InstallReferrerProvider appAttributionId content://com.facebook.katana.liteprovider.usdid.UsdidValu esProvider Google Advertising ID, Android Privacy-Sandbox attribution, and installreferrer attribution are all wired in. // UsdidRequestInterceptor — cleaned static { loadLibrary("usdidinterceptor"); } mHybridData = initHybrid(true, usdidConfig.endpoints()); getLiteUsdid() { return tokenManager.token ?? prefs.getString("usdid_lite_token", ""); } // injected into requests Read: this is the mechanism by which "Instagram" and "Facebook" aren't really separate from the data's point of view — a shared device identity is read across the app boundary and attached to network calls. 11 · IDENTITY US-DID INTERCEPTOR · CROSS-APP PROVIDER · AD IDS
  13. 12 — THE AD LEDGER STRUCTURE VERIFIED A local journal

    of every ad touch. "Quantum Signals" is an on-device ledger of ad interactions. Each IGQuantumSignalsSignal is a typed record — surface, ad key, fields, source, timestamps, flags — appended to a local journal file. // IGQuantumSignalsSignal — fields (cleaned) class IGQuantumSignalsSignal { IGQuantumSignalsType type; IGQuantumSignalsSurface surface; // AdInteraction, Cta, Iab, ... IGQuantumSignalsAdKey adKey; IGQuantumSignalsFields fields; IGQuantumSignalsSignalSource source; long timestamp; int ordinal; boolean flags[2]; } // persisted to: quantum_signals_journal.jsonl SIGNAL TYPES OBSERVED AdInteraction Cta IGQuantumSignalsJournal Engagement Iab MediaTap ProfileVisit IGQuantumSignalsSponsoredLedger SeenState Xout IGQuantumSignalsColdStartActivation Read: ad feedback isn't only sent and forgotten — a structured, replayable ledger of it is kept on the device, including "seen but not tapped" (SeenState) and rejection (Xout). Negative space is recorded as carefully as clicks. 12 · QUANTUM SIGNALS TYPED AD LEDGER · QUANTUM_SIGNALS_JOURNAL.JSONL
  14. 1 3 — C O N TAC T S ,

    T E L E M E T R Y & P E R M I S S I O N S The rest of the surface area. C O N TA C T U P L O A D ( C C U ) DEVICE TELEMETRY PERMISSION + CONFIG GATED VERIFIED XCCUWorker is a periodic WorkManager job BatterySignalPlugin emits (xccu_periodic_upload, xccu_catchup_upload) that runs a FULL {"sta":"Charging|Unplugged|Full","lvl":pct} under key contact sync via IgXCCUClient ("CCU_BACKGROUND_PING"). "bat". Plus screen, thermal, audio, and time-spent collectors. Guarded by a runtime permission check and MobileConfig flags. DeviceBatteryMetricsCollector ContinuousContactUploadApi clientThermalState ContactPointsUploader clientScreenBrightness AGGREGATED_TIME_SPENT_PER_DAY files/addressbook_xccu S E N S I T I V E P E R M I S S I O N S D E C L A R E D — A U T H O R I TAT I V E ( A A P T ) , O F 8 2 TOTA L CAMERA RECORD_AUDIO READ_MEDIA_VIDEO WRITE_CALENDAR N OTA B LY A B S E N T READ_CONTACTS READ_PHONE_STATE MEDIA_PROJECTION GET_ACCOUNTS READ_PHONE_NUMBERS ACCESS_FINE_LOCATION NEARBY_WIFI_DEVICES FOREGROUND_SERVICE_LOCATION ACCESS_MEDIA_LOCATION BLUETOOTH_CONNECT READ_MEDIA_IMAGES USE_BIOMETRIC READ_CALL_LOG maxSdk28 ACTIVITY_RECOGNITION — no step/motion-activity permission. Any SMS permission — none declared. BODY_SENSORS — not declared. Read: these are the standard "big social app" permissions, each gated at runtime. What you don't see matters too — the absences on the next page kill several common myths. 13 · CONTACTS · TELEMETRY · PERMISSIONS CCU GATED · 82 PERMISSIONS · KEY ABSENCES
  15. 14 — MYTHS VS. CODE What the evidence does not

    support. A teardown is only as credible as the claims it refuses to make. Here is where the popular "Instagram spies on everything" story runs out of code. ✕ "It's always listening to your mic." RECORD_AUDIO and FOREGROUND_SERVICE_MICROPHONE exist — consistent with calls, voice messages, and Reels audio. The voice-activity detector (light_vad_coeff.bin) is an RTC/calls component. No passive-audio-to-ads path appears in the static evidence. ✕ "It knows if you're walking or lying in bed." There is no ACTIVITY_RECOGNITION permission and no walking/lying/sleep classifier. Motion sensors (accelerometer, gyroscope, gravity, shake) are present for camera/AR and orientation — not posture inference. ✕ "It scans every app on your phone." The install probe is a curated 23-package list behind <queries>, gated, throttled to 24h, and only logged when sampled. It is specific, not a full inventory. ✕ "There are 31 AI models spying on you." Round numbers don't survive contact with Voltron. Roughly a dozen on-device model families appear; many heavy models are server-side; weights are often downloaded after install, so the active set changes. ✕ "Hair / face detection = profiling you." Segmentation models (hair, person, body) are camera & AR effects. Real, but not feed/ad profiling. 14 · MYTHS VS. CODE CREDIBILITY = THE CLAIMS REFUSED
  16. 15 — RECEIPTS The exact strings. For the "source?" crowd.

    Class names, field names, and assets extracted from the APK. Static analysis, not a captured request. Casper com.meta.casper.Casper · com.instagram.casper.IgSignalsCasper · META_CASPER_APP_START · next_app_start_prediction_start/end · META_CASPER_HISTORICAL_APP_SESSIONS_V1 · ig4a_meta_casper_mldw_ir.json (retentionInSec 604800) Session vector 190 × ranking_session_* · 100 time_since_* · 24 *_incl_sleep · 61 ad-related · max_scroll_depth_current_surface · scroll_reversal_count · video_dwell_time_sum/max In-app browser time_since_last_ad_iab_contact_autofill · ..._iab_contact_payment_autofill · ..._iab_navigation · ..._iab_no_bounce · ..._iab_offapp_exit Last session p13n_last_session_duration_ms · _end_time_ms · _max_scroll_depth · _ad_impression_count · _did_like_post · _did_open_comments Carrera / interest CarreraPopulateInferredInterestsMutation · arg_inferred_interests_list · matched_taxonomy_interest · interest_ids_to_keep · pinned_carrera_interests · TUNE_YOUR_ALGO_INTEREST_KEYWORD · CARRERA_ALGORITHM_CONTROL_CENTER Taxonomy topics_v9 · subtopics_v9 · embedding_v9 · contextual_rec_embedding_v9 · adtaxon_i18n_top1_l7_prediction · ranking_info_recommender_type Personalization IGAdsPersonalizationMetadataQuery · xig_ads_personalization_features · Feature(FeatureType.DOUBLE, …) · feature_count · FAILURE_NULL_PERSONALIZATION_FEATURES · com.instagram.odml.p13n.room.* ODML odml_app_entry_model_android · odml_ads_prefetch_model · odml_ads_tooltip_model_android · odml_swipe_up · IG_ADS_ODML_SCROLLING_SPEED · IG_ADS_ODML_PREDICT_AND_TRAIN · StoryPrefetchODML · ShareSheetRankingMlEngineWrapper · abandon_model_probability_ppm AI apps <queries> 23 packages · EnumC2446309jS · Ig4aAiAppsDetectorManager · getPackageInfo · installed_apps · odin_ai_apps_detector Image (camera roll) gallery_media_metadata (local, via MediaStore) · Siglip2OnDeviceImageEmbedder · visual_embeddings · scanner_versions · person/food/nature/landmark/document/pet/aesthetic/blur _score · locality/sub_admin_area/country_name (geo from EXIF) · ALLOW/DENY_ACCESS_TO_DEVICE_CAMERA_ROLL · CAMERA_ROLL_INSPIRATION_* Identity FDID · PhoneID · US-DID · FEO2 · UsdidRequestInterceptor (native usdidinterceptor) · content://com.facebook.katana.liteprovider.usdid.UsdidValuesProvider Ads ledger IGQuantumSignalsSignal · IGQuantumSignalsFields · IGQuantumSignalsJournal · IGQuantumSignalsSponsoredLedger · quantum_signals_journal.jsonl · AdInteraction/Cta/Iab/SeenState/Xout Contacts XCCUWorker · ContinuousContactUploadApi · ContactPointsUploader · files/addressbook_xccu · xccu_periodic_upload Battery BatterySignalPlugin ({"sta","lvl"} key "bat") · DeviceBatteryMetricsCollector · chargingRealtimeMs APK com.instagram.android 454.0.0.54.77 · versionCode 386014758 · minSdk 28 / target 37 · sha-256 255374e8…0783d371 Signature Scheme v3 + v3.1 verified · signer O=Meta Platforms Inc. (3a10c50c…c014) · legacy lineage cert CN=Kevin Systrom, O=Instagram Inc (5f3e50f4…e305) Permissions 82 uses-permission (aapt) · no SMS · no ACTIVITY_RECOGNITION · no BODY_SENSORS · READ_CALL_LOG maxSdk28 15 · RECEIPTS NAMES EXTRACTED FROM THE APK
  17. 16 — VERDICT What I'd stake, and what I wouldn't.

    VERIFIED Class/field/asset presence: Casper feature build & 7-day store; the 190 fields & their categories; AI-apps path & gating; PersonalizationFetcher fetch/parse/store; Quantum Signals record shape; SigLIP2 columns; US-DID interceptor; battery JSON; declared permissions. HIGH Casper predicts next open and drives prefetch; US-DID read across the Meta app boundary; contact upload is a real, gated pipeline. INFERRED Exact downstream use of individual signals; which feature IDs dominate ranking; the precise action Casper's prediction triggers. NOT PROVEN That any given field is transmitted, or how often; that image embeddings leave the device; that any feature is active on a specific account. Server-side ranking is not in the APK. B OT TO M L I N E The story isn't a secret microphone. It's an architecture: dense per-session feature vectors, a stack of on-device models, server-computed features synced back down, and a cross-app identity binding it together — nearly all of it switchable by remote flag without an app update. Most of this is broadly consistent with what Meta's privacy policy describes as "activity, device signals, and ads personalisation." What a teardown adds is the granularity the policy never shows: that recency survives sleep, that in-app-browser payment autofill is a named signal, that your scroll-backs and x-outs are labelled training examples, and that "when will you be back?" is itself a modelled product. It doesn't need to read your mind. It just needs to read your thumb — and the clock. 16 · VERDICT CAPABILITY, HONESTLY BOUNDED