# AppXray Reverse-Engineering Report

> Target: Duolingo (com.duolingo)

| Field | Value |
|---|---|
| Package | `com.duolingo` |
| Version | 6.79.5 (code: 2361) |
| Size | 246 MB (XAPK), main APK 164 MB |
| Min SDK | 29 (Android 10) |
| Target SDK | 36 (Android 16) |
| Architecture | Native Kotlin + Jetpack Compose + Unity (mini-games) |
| DEX Files | 11 (~63 MB bytecode) |
| Activities | 242 |
| Services | 17 |
| Report Date | 2026-05-26 |
| Source | APK decompilation + string extraction + manifest analysis |

---

## Key Findings

1. **IronSource mediation at the center** -- Unity Ads, Vungle, Moloco, AdMob, Facebook AN, and Pangle all wired through IronSource / Unity mediation stack (3,952+ IronSource class references in bytecode).
2. **Facebook Audience Network loaded as hidden DEX** -- `audience_network.dex` (~5 MB) in `assets/`, same cold-start optimization pattern as CamScanner.
3. **7+ ad networks for free-tier monetization** -- plus Google Play Billing for Super / Plus subscriptions (no RevenueCat detected).
4. **Multiple staging APIs in production** -- `android-api-stage`, `goals-api-stage`, `goals-api-stage-2/3`, `infra-edge-gateway-stage-cf`.
5. **Kotlin + Jetpack Compose** main UI; **Unity** used for specific game experiences (`UnityActivity`, chess promos).
6. **Adjust** for attribution; **Sentry** with dedicated `duolingo-sentry.sentry.io` (session replay URLs in strings).
7. **China split** -- `android-api.duolingo.cn` alongside global `android-api.duolingo.com`.
8. **First-party ad surfaces** -- `CustomNativeAdActivity`, `FullscreenNetworkNativeAdActivity`, `PlusPromoVideoActivity` (session-end upsell).

---

## 1. Architecture Overview

### Core Architecture

Duolingo is a **large native Android app** built primarily with **Kotlin and Jetpack Compose** (4,000+ Compose references in DEX). Select experiences (chess, some interactive content) route through **Unity** (`com.duolingo.feature.unity.UnityActivity`, `UnityPlayerGameActivity`).

```
User-facing app
  |
  +-- Kotlin / Jetpack Compose -- Lessons, profile, leagues, onboarding, Plus flows
  |     |
  |     +-- OkHttp + Retrofit -- API layer
  |     +-- Room -- Local persistence
  |     +-- ExoPlayer -- Audio / video (lessons, promos)
  |     +-- Lottie / Rive -- Animations (modular_rive_lily.json, CDN Lottie)
  |
  +-- Unity runtime -- Chess and selected game modules
  |
  +-- Ad mediation layer -- IronSource hub -> Unity, Vungle, Moloco, AdMob, Meta, Pangle
```

### Component Count

| Component | Count |
|---|---|
| Activities | 242 |
| Services | 17 |
| Broadcast Receivers | 17 |
| Content Providers | 12 |

### Notable First-Party Modules (from Activity names)

| Module | Activity / clue |
|---|---|
| Lessons / session | `com.duolingo.app.*`, session end flows |
| Super / Plus monetization | `PlusPurchaseFlowActivity`, `duolingo.com/settings/super` |
| Ads (free users) | `feature.ads.CustomNativeAdActivity`, `FullscreenNetworkNativeAdActivity` |
| Leagues | `feature.leagues.interstitial.LeaderboardInterstitialActivity` |
| Math / Music | `feature.math.*`, cloudfront score XML assets |
| Duolingo English Test | `englishtest.duolingo.com` deep links |
| Schools / classrooms | `schools.duolingo.com/api/*` |
| Video call / AI | `ai.videocall.promo.VideoCallPurchasePromoActivity` |
| Family plan | `plus.familyplan.*`, `invite.duolingo.com/family-plan/` |

---

## 2. Core Feature Modules

### Monetization UX (Free vs Paid)

| Surface | Purpose |
|---|---|
| `PlusPurchaseFlowActivity` | In-app subscription purchase flow |
| `PlusPromoVideoActivity` | Video ad / promo after sessions (session-end monetization) |
| `ProxyBillingActivity` / `V2` | Google Play Billing |
| `VideoCallPurchasePromoActivity` | AI video call upsell |
| `LeaderboardInterstitialActivity` | League screen interstitial placement |

**Model:** Freemium -- ads + upsell interstitials for free users; **Google Play Billing** for Super/Plus (gems, family plan). Strings reference `PendingPurchase`, `QueryPurchasesParams` -- native Billing Library, not third-party subscription SDK.

### Social & Growth

| Feature | Evidence |
|---|---|
| Friend invites | `AddFriendsFlowActivity`, `invite.duolingo.com` |
| Contacts | `READ_CONTACTS`, `AddPhoneActivity` |
| Referral / family | `invite.duolingo.com/family-plan/%s` |

---

## 3. API & Endpoint Analysis

### Production APIs (duolingo.com)

| Endpoint | Purpose |
|---|---|
| `android-api.duolingo.com` | Primary Android API |
| `android-api-cf.duolingo.com` | Cloudflare-fronted API variant |
| `android-api.duolingo.cn` | China region API |
| `goals-api.duolingo.com` | Goals / learning path (inferred) |
| `birdseye.duolingo.com` | Internal/analytics tooling (inferred) |
| `drive-thru.duolingo.com` | Feature flag / config delivery (inferred) |
| `diagnostics.duolingo.com/user-summary/` | Diagnostics |
| `duolingo-maker-prod.duolingo.com/animation/lottie` | Lottie asset CDN |
| `localization-duostrings.duolingo.com` | Localized strings |
| `tts-data.duolingo.com` | Text-to-speech |
| `math-cdn.duolingo.com` | Math module assets |
| `simg-ssl.duolingo.com` | Avatars, Lottie, promo videos |
| `schools.duolingo.com/api/1`, `/api/2` | Duolingo for Schools |
| `englishtest.duolingo.com` | DET (English Test) integration |
| `store.duolingo.com` | Merch shop deep links |
| `stories.duolingo.com` | Stories feature |
| `zombie.duolingo.com` | Internal codename endpoint |

### Staging / Test Endpoints (in production build)

| Staging Endpoint |
|---|
| `android-api-stage.duolingo.com` |
| `goals-api-stage.duolingo.com` |
| `goals-api-stage-2.duolingo.com` |
| `goals-api-stage-3.duolingo.com` |
| `infra-edge-gateway-stage-cf.duolingo.com` |
| `duolingotest.zendesk.com` |

### Third-Party Service Endpoints (sample)

| Endpoint | Service |
|---|---|
| `duolingo-sentry.sentry.io` | Sentry (error + replay) |
| `firebaseinstallations.googleapis.com` | Firebase |
| `googleads.g.doubleclick.net` | AdMob / Google Ads |
| `gateway.unityads.unity3d.com` | Unity Ads |
| `adx.ads.vungle.com` | Vungle |
| `api16-access-sg.pangle.io` | Pangle (TikTok) |
| `config.ads.vungle.com` | Vungle config |
| `imasdk.googleapis.com/admob/sdkloader/` | AdMob IMA / video |

---

## 4. Advertising & Monetization

### Ad Networks (7+ detected)

| Network | Package / evidence | Role |
|---|---|---|
| **IronSource** | `com.ironsource.mediationsdk` | **Mediation hub** -- ControllerActivity, InterstitialActivity, TestSuite |
| **Unity Ads** | `com.unity3d.services.ads` | Mediated network + `gateway.unityads.unity3d.com` |
| **Google AdMob** | `com.google.android.gms.ads` | Banner, interstitial, native (MRAID v3 assets in strings) |
| **Facebook Audience Network** | `com.facebook.ads` + `audience_network.dex` | Dynamic DEX load (~5 MB in assets) |
| **Pangle (ByteDance)** | `com.bytedance.sdk.openadsdk` | 12+ TT* ad Activities (rewarded, interstitial, app open) |
| **Vungle** | `com.vungle.ads` | Video / MRAID |
| **Moloco** | `com.moloco.sdk` | MraidActivity, VastActivity, ORTB paths in SDK |
| **AppLovin** | `com.applovin` (lower reference count) | Present but lighter integration |

### Ad Format Evidence (Manifest Activities)

| Format | Networks |
|---|---|
| Rewarded video | Pangle (`TTRewardVideoActivity`), Unity, IronSource |
| Interstitial | AdMob, Pangle, Vungle, IronSource, Moloco |
| App open | Pangle (`TTAppOpenAdActivity`) |
| Native / custom | `CustomNativeAdActivity`, `FullscreenNetworkNativeAdActivity` |
| Fullscreen WebView | Unity `FullScreenWebViewDisplay`, Moloco MRAID |

### Monetization Strategy Analysis

1. **IronSource-led mediation** -- Highest SDK surface area; Unity Ads tightly integrated (`com.unity3d.ironsourceads`). Typical setup: IronSource MAX or LevelPlay managing waterfall/bidding across networks.
2. **Session-end ad pressure** -- `PlusPromoVideoActivity`, `LeaderboardInterstitialActivity` suggest ads tied to natural break points (after lesson, league screen).
3. **Hidden Facebook DEX** -- Same 5 MB `audience_network.dex` pattern; defers Meta SDK load until needed.
4. **Subscriptions separate from ads** -- Play Billing + `duolingo.com/settings/super`; gems and family plan strings. No RevenueCat / Superwall found in DEX.
5. **Debug tooling left in** -- `AdsDebugScreenActivity` for internal ad QA.

### In-App Purchases

| SDK | Purpose |
|---|---|
| Google Play Billing | Super, Plus, gems, family plan |
| `com.android.billingclient` | Billing Library v6+ patterns (`PendingPurchasesParams`, multi-item queries) |

---

## 5. SDK & Third-Party Libraries (Full List)

### Advertising & Mediation (8)

| SDK | Notes |
|---|---|
| IronSource | Mediation core |
| Unity Ads | Ads + `UnityPlayerGameActivity` for games |
| Google AdMob | Primary Google stack |
| Facebook Audience Network | Hidden DEX |
| Pangle | ByteDance, full format set |
| Vungle | Video |
| Moloco | Programmatic / ORTB |
| AppLovin | Secondary |

### Analytics & Attribution (3)

| SDK | Purpose |
|---|---|
| Adjust | `com.adjust` -- MMP / attribution |
| Firebase | Analytics, Installations, Crashlytics docs linked |
| Sentry | `io.sentry`, `duolingo-sentry.sentry.io`, replay explore URLs |

### Crash & Monitoring (2)

| SDK | Notes |
|---|---|
| Sentry | Primary crash + session replay |
| Firebase Crashlytics | Settings endpoint in strings |

### Support & CRM (1)

| SDK | Purpose |
|---|---|
| Zendesk | `duolingotest.zendesk.com`, help center CSS in assets |

### Media & UI (6)

| SDK | Purpose |
|---|---|
| Jetpack Compose | Modern UI toolkit |
| ExoPlayer | Audio/video playback |
| Lottie | Animations |
| Rive | `modular_rive_lily.json` |
| Glide | Likely image loading (typical; verify in deeper pass) |
| OkHttp / Retrofit | Networking |

### Payments (1)

| SDK | Purpose |
|---|---|
| Google Play Billing | Subscriptions and IAP |

### Other

| SDK | Purpose |
|---|---|
| Dagger / Hilt hints | DI (`dagger` strings) |
| Room | Local DB |
| WorkManager | Background tasks |

---

## 6. Permissions Analysis

### Total: 40 permissions

#### High Sensitivity

| Permission | Risk | Usage Context |
|---|---|---|
| `RECORD_AUDIO` | HIGH | Speaking exercises, pronunciation |
| `READ_CONTACTS` | HIGH | Friend discovery / invites |
| `READ_EXTERNAL_STORAGE` / `WRITE_EXTERNAL_STORAGE` | MEDIUM | Legacy storage |
| `USE_BIOMETRIC` / `USE_FINGERPRINT` | MEDIUM | Account security |
| `DETECT_SCREEN_CAPTURE` | MEDIUM | Anti-cheat / content protection |

#### Ad & Tracking (5)

| Permission | Purpose |
|---|---|
| `ACCESS_ADSERVICES_AD_ID` | Privacy Sandbox ad ID |
| `ACCESS_ADSERVICES_ATTRIBUTION` | Attribution API |
| `ACCESS_ADSERVICES_TOPICS` | Topics API |
| `com.google.android.gms.permission.AD_ID` | GAID |
| `BIND_GET_INSTALL_REFERRER_SERVICE` | Install attribution (Adjust) |

#### Monetization

| Permission | Purpose |
|---|---|
| `com.android.vending.BILLING` | In-app purchases |

---

## 7. Technical Implementation Details

### Dynamic DEX Loading (Facebook AN)

```
assets/audience_network.dex  (~4.8 MB)
```

Loaded at runtime to keep cold start lean while retaining Meta fill.

### Build & Obfuscation

| Property | Value |
|---|---|
| Multi-DEX | 11 files |
| Target SDK | 36 |
| Split APKs | ABI + density splits in XAPK |
| Sentry debug meta | `sentry-debug-meta.properties` in assets |
| Experiments config | `experiments.duostrings.json` -- feature flags / A/B |

### Unity Integration

Unity is **not** the main shell -- it powers specific game modules (chess promos reference `DuolingoInterstitial_ChessLaunchPromo`). Main app navigation remains Compose-native.

### Comparison to CamScanner (same analyst)

| Dimension | CamScanner | Duolingo |
|---|---|---|
| Ad networks | 6 | 7+ |
| Mediation lead | AdMob + PubMatic bidding | IronSource + Unity |
| UI stack | Native + FlutterBoost | Kotlin Compose + Unity games |
| Subscription SDK | Play Billing | Play Billing (no RevenueCat) |
| Hidden Facebook DEX | Yes | Yes |
| Staging in prod | 6 endpoints | 6+ endpoints |

---

## Summary

Duolingo v6.79.5 is a **mature freemium education app** with a **heavy ad mediation stack centered on IronSource**, seven monetization networks for free users, and **native Play Billing** for Super/Plus. The codebase is **Kotlin/Compose-first** with **Unity** for select games, **Adjust + Sentry + Firebase** for measurement, and **regional API split** (`.com` vs `.cn`). The hidden Facebook DEX and multiple staging hostnames mirror patterns seen in other top-grossing consumer apps.

---

*Generated by AppXray -- [blackorange.org](https://blackorange.org)*
