Beginner

Can I have API keys in my Unity game?

Yes, a Unity game can include some kinds of keys. But the important question is what kind of key it is. There is a big difference between a public identifier and a private secret.

A private key gives privileged access to something important. That could be database manipulation, cloud storage writes, GitHub access, payment tools, admin APIs, or AI service keys like a ChatGPT API key. Never store those in a game you ship to players.

A public key is designed to be visible. It may be a simple project identifier, a client ID, a public analytics key, a restricted map key, or a URL. Public values can exist in the client, but they still need limits and server-side validation.

The core rule is simple: everything client-side is accessible. A Unity build runs on the player's device. If the player controls the device, they can inspect files, memory, network traffic, and runtime behavior.

Why keys get exposed

Keys get exposed because the game needs data to run. If a value is inside the build, it can be copied from the build. If a value appears in memory, it can be read from memory. If a value is sent over the network, it can be observed with proxy tools.

Attackers do not need your full source project. They can inspect the shipped game. In a Unity game, they may search assemblies, native binaries, metadata, resource files, config files, asset bundles, logs, or saved preferences. Plain strings are often the first thing they search.

Common examples include:

  • API URLs that reveal internal service names.
  • Hardcoded bearer tokens or admin keys.
  • Firebase, database, or storage keys used without safe rules.
  • AI service keys that can run up cost if abused.
  • Test endpoints or staging credentials left in release builds.

Once a private key is public, you should treat it as stolen. Rotate it, remove it from the client, check logs for abuse, and move the privileged action to your backend.

Why IL2CPP isn't enough

IL2CPP is useful. It converts managed C# code into native code, which usually makes casual decompilation harder than a Mono build. But IL2CPP is not a secret manager.

Strings can still exist in the final build or appear at runtime. Metadata can still reveal useful names. Network traffic can still show where the game connects. A debugger or memory tool can still inspect values after they are loaded.

This is why a private key does not become safe just because the build uses IL2CPP. IL2CPP raises the effort, but it does not change the trust boundary. The client is still controlled by the player.

String encryption techniques

String encryption, also called string obfuscation, hides readable strings in the shipped build. Instead of storing a clear value like an endpoint, license marker, or public identifier, the build stores an encoded version and restores it when needed.

This can protect public values that would help an attacker understand your systems. It can make simple string searches less useful. It can also hide method names, feature flags, URLs, and license-check messages from basic static analysis.

Obfuscator can help with this kind of build-time protection. The goal is not to make a private key safe. The goal is to stop giving attackers a clean map of your game.

Runtime decryption

Runtime decryption means the game only reveals a protected string when it needs to use it. For example, the build may store an encrypted URL and decrypt it right before a request.

This is better than leaving every string readable in the file. But it is still not perfect. If the game can decrypt a value, an attacker can try to watch the game after it decrypts that value. They may inspect memory, hook the method, or log the result.

Use runtime decryption to reduce easy discovery. Do not use it as an excuse to ship private keys. Private keys belong on the server, where the player cannot directly read or patch the logic.

Common mistakes

The most common mistake is treating the Unity client like a trusted backend. It is not. A real player may use the official game, but an attacker can use a modified game, a script, a proxy, or a custom tool that pretends to be the game.

  • Shipping private keys: database passwords, GitHub tokens, OpenAI keys, and admin service tokens must never be in the client.
  • Only checking on the client: a local check can be patched. Important actions need server validation.
  • No rate limits: public endpoints can still be abused if there are no limits.
  • Trusting public keys too much: a public key should identify a project, not grant full access.
  • Forgetting build variants: staging keys and test URLs often leak because they were left in release builds.

A safer setup is to let the game talk to your backend. Your backend keeps private keys, checks player identity, validates purchases, applies rate limits, and calls third-party services. The client can ask for an action, but the backend decides whether that action is allowed.

Do

  • Keep private keys, admin tokens, database credentials, and AI service keys on your backend.
  • Use public keys only when the provider says they are safe to expose.
  • Protect public identifiers and URLs with string obfuscation when they would help attackers map your systems.

Don't

  • Do not ship database passwords, GitHub tokens, ChatGPT keys, or privileged service keys in the game.
  • Do not assume IL2CPP makes strings or constants secret.
  • Do not trust requests only because they came from your Unity client.
FAQ

Frequently asked questions.

Short answers to common questions developers ask after reading this article.