← All Posts

How to Extract API Keys from iOS Apps

2026-02-28 · KVProxy Team


If you've ever wondered how hard it is for someone to steal an API key from your iOS app, the answer is: not very.

Anyone with a copy of your app (from the App Store, TestFlight, or an ad-hoc build) can extract embedded secrets in a few minutes using tools that ship with macOS. No jailbreak, no special hardware.

This post walks through exactly how it's done, using a small example app that calls the ChatGPT API with a hardcoded key. By the end, you'll see why shipping API keys in mobile binaries is a losing game, and what to do instead.


Why This Matters

Mobile apps are distributed binaries. Everything you compile into the app: code, resources, and yes, string literals like API keys — ends up in a form that can be inspected. Obfuscation and "security through obscurity" might slow a casual snoop, but they don't stop a determined attacker.

Once a key is extracted:

  • Usage abuse — Someone can run up your API bill or hit rate limits.
  • Account compromise — Keys tied to your account can be revoked or used for fraud.
  • Reputational risk — Leaked keys can be sold or shared.

The only robust approach is to never put the key in the app in the first place. Before we get to that, here's how the extraction actually works.


The Example App

Imagine a simple iOS app that uses the OpenAI Chat Completions API. The developer has added a service that holds the base URL and API key in code:

struct ChatGPTService {
    private let baseURL = "https://api.openai.com/v1/chat/completions"
    private let apiKey = "sk-abcdef1234567890abcdef1234567890abcdef12"

    func generateText(prompt: String) async throws -> String {
        ...
    }
}

The key is marked private, but that only affects Swift's visibility rules. At compile time, the string "sk-abcdef1234567890abcdef1234567890abcdef12" is embedded in the app binary. Private doesn't mean "not in the binary"; it just means "not exposed to other Swift code."


Step 1: Get an IPA

To extract secrets, an attacker needs the app in a form they can unpack.

IPA files can be exported from iOS devices using off-the-shelf tools like Apple Configurator or iMazing.

For this demo, we'll assume we have an IPA file for the example app named Extraction.ipa.


Step 2: Unzip the IPA

An IPA is just a ZIP archive. Unzip it and you get a Payload folder containing the app bundle:

unzip Extraction.ipa

Example output:

Archive:  Extraction.ipa
   creating: Payload
   creating: Payload/Extraction.app
   creating: Payload/Extraction.app/_CodeSignature
  inflating: Payload/Extraction.app/embedded.mobileprovision
  inflating: Payload/Extraction.app/Extraction
  inflating: Payload/Extraction.app/Info.plist
  inflating: Payload/Extraction.app/PkgInfo
  inflating: Payload/Extraction.app/_CodeSignature/CodeResources

The main executable is Payload/Extraction.app/Extraction — that's the compiled binary that contains your code and every string literal you embedded.


Step 3: Run strings and Search for Secrets

The strings command (available on macOS and Linux) prints printable character sequences from a binary. It's intended for debugging, but it's also perfect for finding embedded keys, URLs, and other literals.

Search for something distinctive — like the sk- prefix used by OpenAI API keys:

strings Payload/Extraction.app/Extraction | grep "sk"

Output:

sk-abcdef1234567890abcdef1234567890abcdef12

There it is: the full API key, in plain text, with no reverse engineering required.


What This Proves

Hardcoded API keys in iOS apps are not secret. They live in the binary as plain strings (or trivially decoded data).


What to Do Instead

The fix is simple in principle: never put the key in the app. Something you control — a backend or a proxy — should hold your secrets and communicate with the 3rd party service on behalf on your app.

Building and maintaining your own backend just to proxy API calls is a lot of work. For many teams, that's overkill when all you need is to call an API without shipping the key.

KVProxy was designed for this exact purpose. Just add your API keys in the KVProxy dashboard and update a single line of code to your iOS app. Your app will then automatically route relevant requests through KVProxy, which securely injects your keys—so your app never touches them directly.

Ready to try it? Head to kvproxy.com to get started, or check out the KVProxy iOS Demo to see it in action.