Guide · App Store Connect

TestFlight external testers: setup, limits and troubleshooting

To add TestFlight external testers, create an external group in the TestFlight tab of App Store Connect, add a processed build, and invite up to 10,000 people by email or public link. The first build you submit goes through a full TestFlight App Review; later builds of the same version may not need one.

Internal testers skip that review. Up to 100 App Store Connect users on your team can install a build as soon as it's processed, cleared for export compliance and added to their group. Every build expires 90 days after upload. When testers say TestFlight shows no builds, the cause is usually one of these: missing compliance, a build that was never added to their group, a build still in review or never released to testers, an expired build, or a device that can't run it.

By Redjan Hysa, founder of MetaRun · Facts checked October 12, 2026

external testers per app
10,000
internal testers, all App Store Connect users
100
a build stays testable after upload
90 days
builds you can submit to TestFlight App Review
6 per 24 h
devices one tester can install a beta on
30
minimum iOS or iPadOS for the TestFlight app
iOS 16
01 · Reference

Reference tables

TestFlight internal vs external testers
DetailInternal testersExternal testers
WhoApp Store Connect users with the Account Holder, Admin, App Manager, Developer or Marketing roleAnyone, invited by email or through a public link
Limit10010,000 per app
ReviewNoneTestFlight App Review on the first build; later builds of a version might skip the full review
New buildsOptional automatic distribution per group (Xcode Cloud builds are always added by hand)Added to the group one at a time
TestFlight Internal Only buildsAllowedNot allowed
What you seeName and emailName and email for email invites; Anonymous for public link testers
TestFlight build statuses
StatusWhat it meansWhat to do
Missing ComplianceNo export compliance answer yet. Nobody can test it.Answer the encryption questions on the build.
Waiting for Export Compliance Review, In Compliance ReviewYour encryption documentation is with Apple.Wait.
Ready to SubmitInternal testers can use it; external testing needs review.Add it to an external group and submit for review.
Waiting for Review, In Beta ReviewTestFlight App Review has it.Wait. External testers can't install yet.
Ready to TestTestable, but no testers have it (or you chose to notify them manually).Add a group, or click Notify Testers.
TestingAt least one group or tester has it.Nothing.
RejectedTestFlight App Review rejected it; it can't be used in TestFlight.Read the details in App Review, fix, upload a new build.
ExpiredPast its 90-day window, or expired by you.Upload a new build.
Not Available for TestingThe provisioning profile is missing an application identifier.Upload a new build with a correct profile.
Invalid BinaryThe upload didn't meet requirements.Fix the issues and upload again.

Apple's App build statuses reference.

02 · By hand

How to add external testers in TestFlight

You need the Account Holder, Admin or App Manager role. The example sends build 312 of version 2.4 to a group called Beta Club.

  1. 01

    Fill in Test Information

    In the TestFlight tab, under Additional, click Test Information. The Beta App Description is required, and the Feedback Email is where testers reach you. Fill in the Beta App Review contact and, if the app needs a login, a sign-in account.

  2. 02

    Clear export compliance

    Under Builds, click the platform, then build 312. If it says Missing Compliance, click Provide Export Compliance Information and answer the questions.

  3. 03

    Create the external group

    Click the add button (+) next to External Testing, name the group Beta Club, and click Create. App Store Connect requires an internal group to exist first.

  4. 04

    Add the build and What to Test

    In the group, click Add Builds, choose the platform, version 2.4 and build 312. Write What to Test (localized versions are optional), decide whether to tick Automatically notify testers, then click Submit Review, or Start Testing if the build is already approved.

  5. 05

    Invite testers

    Click the add button (+) next to Testers to add people by email, pick existing testers or import a CSV. Or click Create Public Link under the group's testers. If you left notification off, go to the build row after approval and click Notify Testers.

03 · Briefing

TestFlight beta app review: what to expect

Adding a build to an external group submits it to TestFlight App Review. Apple reviews the build and its test information; the first build gets a full review and later builds of the same version might not. Only one build per version can be in review at a time, and you can submit up to six builds in 24 hours. Apple doesn't publish a turnaround for beta review (its 24 and 48 hour goals are stated for App Review submissions), so leave a margin before a beta deadline.

On approval, Admins get an email. On rejection the build shows Rejected and can't be used in TestFlight again; the details are in App Review under General in the sidebar, and you appeal by contacting TestFlight App Review. Treat the beta sign-in account like the one you give App Review: it has to work, and it mustn't expire mid-review.

05 · Briefing

Build expiry, What to Test and tester devices

Each build is testable for 90 days from upload, and testers see the days left in TestFlight. Expire Build stops installs early. If you don't expire it, testers keep access even after that build goes live on the App Store. Removing a build from a group doesn't pull it from testers already using it.

What to Test belongs to the build, not the group: everyone with access sees the same text. Write what changed and where to look, for example "New export flow under Settings > Data; try it with 500+ items". Testers need the TestFlight app (iOS or iPadOS 16, macOS 13, tvOS 18, visionOS 1 or watchOS 9 or later) and a device that meets your build's minimum OS. The beta replaces any App Store copy, in-app purchases are free, and subscriptions renew daily, up to six times a week.

06 · Troubleshooting

Common problems and how to fix them

TestFlight shows no builds available, and the build says Missing Compliance

Why: The build has no export compliance answer. Until it does, nobody can test it, internal testers included.

Fix: Open the build in the TestFlight tab and click Provide Export Compliance Information. Add ITSAppUsesNonExemptEncryption to Info.plist so future builds arrive answered.

TestFlight shows no builds available to a tester, but the build is processed

Why: Testers only see builds added to their group or to them individually. For external groups, the build may still be waiting for review, or it was approved with Automatically notify testers off (status Ready to Test).

Fix: Check the Groups column next to the build and add the tester's group. If the status is Ready to Test, click Notify Testers. Xcode Cloud builds always need adding by hand.

TestFlight build expired

Why: Builds stop working 90 days after upload, or earlier if someone clicked Expire Build.

Fix: Upload a new build and add it to the groups. Upload a fresh build every couple of months to keep long-running betas alive.

Build not visible in TestFlight after upload

Why: It's still processing, or it ended as Invalid Binary or Not Available for Testing (a provisioning profile without an application identifier).

Fix: Wait for Apple's processing email; past 24 hours, contact Apple. Fix the reported errors and upload again; a failed upload can reuse its build number.

TestFlight not receiving the invite email

Why: Internal testers get the email only once their group has a testable build. External testers are notified after approval, and only automatically if Automatically notify testers was ticked. Spam filters catch the rest.

Fix: Give the group a testable build first. In Testers, select those still Invited and choose Reinvite. Or send a public link instead.

TestFlight external testers stuck in Waiting for Review

Why: The build is in TestFlight App Review, which checks the build and its test information, so a missing description or a sign-in that doesn't work can get it rejected. A second build of the same version can't enter review until the first is done.

Fix: Complete Test Information while you wait. Don't upload new builds to restart the clock; you can only have one build per version in review.

Testers can't install the build

Why: Their device runs an OS below the build's minimum or below what the TestFlight app needs, the build is for a different platform, they don't meet the public link criteria, or they already use 30 devices. Managed Apple Accounts in reserved domains can't test at all.

Fix: Ask for the device model and OS version. TestFlight only shows Install when a compatible build exists, so lower the deployment target or adjust the criteria if needed.

TestFlight public link full

Why: The link reached the limit you set, or the app reached 10,000 external testers.

Fix: Raise the limit under Manage next to Public Link, or remove inactive testers: filter Testers by sessions, select those with none, and delete them.

07 · With an AI agent

Do it from Claude Code, Codex, Cursor or Xcode with MetaRun

TestFlight work comes in small pieces at awkward times: a build finishes processing while you're in the middle of something, someone has to add it to the right groups, the What to Test field is empty again, and tester feedback sits in a separate tab.

Your agent can do each piece through MetaRun, in the same session where the build was made. Crash feedback and screenshots from testers come back as data the agent can match against your code.

Before you start

  • A build uploaded from Xcode, Xcode Cloud, fastlane or CI.
  • Tester groups set up in App Store Connect.
  • An answer for export compliance, or ITSAppUsesNonExemptEncryption in Info.plist.

How the agent runs it

  1. 01

    Wait for processing

    Your agent reads the build list and reports when the build is processed. A build still processing can't be assigned.

  2. 02

    Clear export compliance

    If the build has no encryption answer, the agent previews the declaration, or reuses an existing one.

  3. 03

    Assign and describe

    Each group assignment and the What to Test text is its own preview.

  4. 04

    Read what testers found

    Crash feedback, crash logs and screenshot feedback come back as structured data, ready to compare with the code.

An example session

When build 312 finishes processing, give it to Internal and Beta Club, with What to Test written from the commits since build 309.

  1. apple_list_buildsBuild 312 processed. No export compliance answer yet.
  2. apple_preview_declare_build_encryptionPreview: exempt encryption, assigned to build 312. Not revertible.
  3. Your agent asks before running apple_apply_declare_build_encryption. You read the preview above and approve.
  4. apple_apply_declare_build_encryptionDeclared.
  5. apple_preview_assign_build_to_groupPreview: build 312 to the Beta Club group.
  6. Your agent asks before running apple_apply_assign_build_to_group. You read the preview above and approve.
  7. apple_apply_assign_build_to_groupAssigned to Beta Club.
  8. apple_preview_set_what_to_testPreview: What to Test in English, from the commits since build 309.

Illustrative: your apps, versions and numbers will differ. The tool names and their order are real.

The MetaRun tools involved

ToolWhat it does
apple_list_buildsreadBuilds with version, build number, processing state and expiry.
apple_list_testflight_groupsreadInternal and external tester groups.
apple_preview_assign_build_to_grouppreview + applyGive a build to a tester group.
apple_preview_set_what_to_testpreview + applyWhat to Test notes for a build, per language.
apple_preview_declare_build_encryptionpreview + applyAnswer export compliance so the build can be tested.
apple_list_testflight_crash_feedbackreadCrash reports testers submitted, with their comments.
apple_get_crash_logreadThe crash log behind a tester's report.
apple_list_testflight_screenshot_feedbackreadScreenshots and comments testers sent from the app.
apple_preview_expire_buildpreview + applyStop testing a build before its 90 days are up.

Each preview has an apply twin that only runs with the confirm token from a fresh preview, and refuses if App Store Connect changed in between.

What Apple enforces along the way

Builds expire after 90 days

A TestFlight build stops working 90 days after upload. Expiring one early is a preview and apply like any other change.

External testing needs Beta App Review

The first build of a version sent to external testers goes through Beta App Review. Internal testers get it as soon as it's processed.

Export compliance can't be undone

Declaring a build's encryption is permanent for that build, so the preview says it's not revertible. Setting ITSAppUsesNonExemptEncryption in Info.plist answers it at upload instead.

MetaRun doesn't upload builds

Xcode, Xcode Cloud, fastlane or your CI uploads the build. MetaRun takes over once it's in App Store Connect.

Set up your agent

Connect once, then ask in plain words. Pick your agent:

Claude Code Anthropic

Run claude mcp add --transport http --scope user metarun https://metarun.dev/api/mcp, then run /mcp in Claude Code and sign in to MetaRun in your browser.

01 · Add the server

Run it in any terminal. --scope user makes MetaRun available in every project; leave it out to limit it to the current one.

claude mcp add --transport http --scope user metarun https://metarun.dev/api/mcp

02 · Sign in

In a Claude Code session, run /mcp, choose metarun and authenticate. MetaRun opens in your browser, where you pick read-only or read and change. From a plain shell, claude mcp login metarun does the same.

/mcp

03 · Optional: add the skills too

The MetaRun plug-in bundles the same server with six mission skills (release handoff, worldwide pricing, localization, review inbox, ASO audit, store media).

claude plugin marketplace add metarun/metarun-skills
claude plugin install metarun-skills@metarun

Then ask Claude Code

  • Ask Claude Code: When build 312 finishes processing, give it to Internal and Beta Club, with What to Test written from the commits since build 309.
  • Ask Claude Code: Pull this week's TestFlight crash feedback and match the stack traces to files in Sources/.
  • Ask Claude Code: Expire every build older than 2.3.

claude -p runs one request with no interactive session. The browser sign-in can't complete inside -p, so sign in once interactively first, or configure the server with a personal access token in CI. Tools missing from --allowedTools are refused in -p mode.

Read-only check, safe to schedule

claude -p "List the latest five builds of com.example.app with processing state, expiry date and the tester groups each one is in. Read only." \
  --allowedTools "mcp__metarun__apple_list_builds,mcp__metarun__apple_list_testflight_groups,mcp__metarun__apple_preview_assign_build_to_group,mcp__metarun__apple_preview_set_what_to_test,mcp__metarun__apple_preview_declare_build_encryption,mcp__metarun__apple_list_testflight_crash_feedback,mcp__metarun__apple_get_crash_log,mcp__metarun__apple_list_testflight_screenshot_feedback,mcp__metarun__apple_preview_expire_build"

Only reads and previews are on that list, so nothing can reach App Store Connect unattended. Run applies in an interactive session where Claude Code can ask you.

Full Claude Code setup guide

Codex OpenAI

Run codex mcp add metarun --url https://metarun.dev/api/mcp; Codex detects MetaRun's sign-in and opens it in your browser.

01 · Add the server

Codex sees that MetaRun offers sign-in and starts it straight away, in your browser. Pick read-only or read and change.

codex mcp add metarun --url https://metarun.dev/api/mcp

02 · Sign in again later

If the sign-in expires or you disconnected it in MetaRun's settings. --no-browser prints the link instead, for SSH sessions.

codex mcp login metarun

03 · Or edit ~/.codex/config.toml

The Codex CLI, the IDE extension and Codex in the ChatGPT desktop app read the same file, so one entry covers all three.

[mcp_servers.metarun]
url = "https://metarun.dev/api/mcp"

Then ask Codex

  • Ask Codex: When build 312 finishes processing, give it to Internal and Beta Club, with What to Test written from the commits since build 309.
  • Ask Codex: Pull this week's TestFlight crash feedback and match the stack traces to files in Sources/.
  • Ask Codex: Expire every build older than 2.3.

codex exec runs one request without an interactive session and with its approval policy set to never. MetaRun's reads and previews still run, because they're marked read-only; anything that would ask is refused.

Read-only check, safe to schedule

codex exec "List the latest five builds of com.example.app with processing state, expiry date and the tester groups each one is in. Read only."

Applies are refused in codex exec by design. Don't set MetaRun's approval mode to approve just to make them pass; keep App Store changes in an interactive session.

Full Codex setup guide

Cursor Anysphere

Add https://metarun.dev/api/mcp to ~/.cursor/mcp.json (or use the install link) and sign in to MetaRun when Cursor opens your browser.

01 · Add to ~/.cursor/mcp.json (or .cursor/mcp.json for one project)

{
  "mcpServers": {
    "metarun": {
      "url": "https://metarun.dev/api/mcp"
    }
  }
}

02 · Or use the install link

Opens Cursor with the server filled in.

https://cursor.com/link/mcp/install?name=metarun&config=eyJ1cmwiOiJodHRwczovL21ldGFydW4uZGV2L2FwaS9tY3AifQ%3D%3D

03 · Sign in

When Cursor connects, MetaRun opens in your browser. Pick read-only or read and change, and you're back in the editor with the tools listed under MCP.

Then ask Cursor

  • Ask Cursor: Write What to Test for build 312 from @CHANGELOG.md.
  • Ask Cursor: Which tester groups have build 310?
  • Ask Cursor: Show me the screenshot feedback testers sent today.

The Cursor CLI runs one request without the editor with agent -p. Allow only the read tools the request needs in ~/.cursor/cli-config.json (Mcp(metarun:tool_name) rules), and keep MetaRun's apply tools out of that list.

Read-only check, safe to schedule

agent -p "List the latest five builds of com.example.app with processing state, expiry date and the tester groups each one is in. Read only." --output-format json

Don't run it with --force for MetaRun: that approves every tool, applies included.

Full Cursor setup guide

Xcode Apple

In Xcode 27, add the plug-in from https://github.com/metarun/metarun-skills (Settings, Intelligence, Plug-ins, Add from URL) and click Sign in next to MetaRun.

01 · Add the MetaRun plug-in

In Xcode 27, open Settings, Intelligence, Plug-ins. Choose Add Plug-in, then Add from URL, and paste:

https://github.com/metarun/metarun-skills

02 · Or with one click

Opens Xcode's plug-in sheet with the repository filled in.

xcode://agent-plugin-clone?repo=https%3A%2F%2Fgithub.com%2Fmetarun%2Fmetarun-skills

03 · Sign in

Install MetaRun from the list, then click Sign in next to it. MetaRun opens in your browser; pick read-only or read and change.

04 · Ask the coding assistant

Claude Agent, Codex and Gemini in Xcode all get MetaRun's tools and its six workflow skills.

Attach build 312 to version 2.4 and tell me what blocks submission.

Then ask Xcode

  • Ask Xcode: I just uploaded build 312 from Organizer. Assign it to the internal group once it's processed.
  • Ask Xcode: Get the crash log for the latest TestFlight crash report and find the line in this project.
  • Ask Xcode: Our Info.plist doesn't declare encryption. Answer export compliance for build 312 as exempt.

Full Xcode setup guide

Claude Anthropic

In Claude, open Customize, Connectors, Add custom connector, paste https://metarun.dev/api/mcp and click Connect to sign in to MetaRun.

01 · Add a custom connector

In Claude, open Customize, then Connectors, and choose Add custom connector. Name it MetaRun and paste the server URL:

https://metarun.dev/api/mcp

02 · Connect

Click Connect. Claude opens MetaRun in your browser to sign in; pick read-only or read and change.

03 · Team and Enterprise

An Owner adds the connector once under Organization settings, Connectors. Each member then clicks Connect and signs in to their own MetaRun account.

Then ask Claude

  • Ask Claude: Has my latest build finished processing?
  • Ask Claude: Send build 312 to my beta testers.
  • Ask Claude: What did testers report this week?

Full Claude setup guide

Apple key stays on MetaRun, encryptedPreview before every writeRecorded, revertible from history
08 · FAQ

Frequently asked questions

What's the TestFlight external testers limit?

10,000 external testers per app, plus up to 100 internal testers who must be App Store Connect users. A public link can carry its own lower limit.

How long does TestFlight beta app review take?

Apple doesn't publish a figure for TestFlight App Review. The first build gets a full review and later builds of the same version might not need one. Leave a margin before any beta deadline.

What's the difference between TestFlight internal and external testers?

Internal testers are App Store Connect users on your team, up to 100, with no review. External testers can be anyone, up to 10,000, and need an approved build.

Why did my TestFlight build expire?

Every build expires 90 days after upload. Upload a new build to keep testing; testers move to it once it's in their group.

How does a TestFlight public link work?

You create it from an external group. Anyone who opens it on a device with TestFlight can join, up to your limit and within any device or OS criteria, and appears as Anonymous in App Store Connect.

What should I write in What to Test?

What changed in this build and where testers should look, in plain steps. It's shown to every group that has the build, so keep group-specific instructions out of it.

Can your agent upload a build to TestFlight?

Not through MetaRun: build upload belongs to Xcode, Xcode Cloud, fastlane or your CI. Everything after the upload (compliance, groups, notes, feedback) works through MetaRun.

Can it read crash reports from testers?

Yes. apple_list_testflight_crash_feedback returns the reports with tester comments and apple_get_crash_log returns the log, which your agent can match against your code.

Does it work with external tester groups?

Yes, internal and external groups both. The first build of a version to external testers still goes through Apple's Beta App Review.

What does export compliance mean here?

Apple's question about whether the build uses non-exempt encryption. The agent can answer it per build, or you can set ITSAppUsesNonExemptEncryption in Info.plist so Apple never asks.

09 · Sources

Sources

Related guides

Guide

Submit for review

The pre-submission checklist, every review status, export compliance, rejections and expedites.

Guide

Phased release

The 7-day percentage schedule, the 30-day pause budget, and what to do when a bad build is rolling out.

Guide

Release notes

What's New and promotional text: the limits, when each one locks, examples for every kind of update, and what App Review rejects.

Guide

Privacy labels

Fill in App Privacy correctly: the 35 data types, tracking, SDKs, privacy manifests and required reason APIs.

All guides

Every App Store Connect guide

Releases, TestFlight, pricing, subscriptions, localization, screenshots and more.

With MetaRun: App Store Connect MCP server

MetaRun

Do this from your AI agent or MetaRun's dashboard, with a preview before every change. 14-day free trial, no card.