Google Play does not have one submit button. It has an account type that decides which rules apply to you, a set of declarations you are legally accountable for, four release tracks, and, for most new solo developers, a closed test that has to run for two weeks before the production track even unlocks. People who plan for an afternoon lose a fortnight here.
This guide runs the path in order and marks the two things that catch people hardest: the closed-testing gate, which applies to some accounts and not others, and the target API level deadline, which moves. It does not promise an approval, and Play approval is not a certification that your app is private, secure, accessible or good.

QUICK ANSWER
How do you publish an app on Google Play?
To publish an app on Google Play you create a Play Console developer account and pay a one-time registration fee, create the app record, complete the store listing and Data safety declarations, upload a signed Android App Bundle to a testing track, then apply for production access and create the production release. Newer personal accounts must first run a closed test.
Decide these four before you pay the registration fee
The first two choices are hard to unwind later, and one of them decides whether you can ship next week or in three weeks.
- Personal account or organization account: Play Console offers two account types, and the choice changes which rules apply. Google states that developers with personal accounts created after 13 November 2023 must run a closed test before their app is eligible for production, and that Production and Pre-registration stay disabled until they do. Organization accounts, and personal accounts created on or before that date, are not subject to that requirement. Checked 2026-08-16.
- A package name you will keep forever: The application ID is reverse-DNS, for example com.yourcompany.yourapp. It cannot be changed after the app is published. A new package name means a new listing with no reviews, no installs and no ranking history, so pick it as if it were a domain.
- A published privacy policy, even if you collect nothing: Google requires every developer with a published app to complete the Data safety form, including apps on closed, open and production tracks, and states that even developers whose apps collect no user data must complete the form and provide a privacy policy link. Apps active only on the internal testing track are exempt. Checked 2026-08-16.
- Twelve real people who will keep the app installed for two weeks: If the closed-testing gate applies to you, this is the long pole and it is a recruiting problem, not a technical one. Google counts only testers who stay opted in continuously; someone who opts in, tests for a few days and opts out does not count, and an opt-out followed by a later opt-in restarts their clock. Line these people up before you build, not after.
Credentials and access
| Credential | Minimum access | Storage and rotation |
|---|---|---|
| Google service account key A JSON key for a Google Cloud service account that has been invited into Play Console and granted release permissions for this app | The narrowest Play Console permission set that can upload to the tracks you automate, scoped to this one app rather than to the whole developer account. | The build environment as a secret value. In a Playcode project the agent writes it with SetEnv marked secret, so it reaches the process environment the store tooling reads and never appears in chat, code, or a committed file. Delete the key in Google Cloud and revoke the account invitation in Play Console when a contractor leaves or a key is exposed. A JSON key is a bearer credential: anyone holding it can push a release. |
| Expo access token A personal access token for the Expo account that owns the build project, read by eas-cli as EXPO_TOKEN | The Expo account or organization that owns this one project, so a leaked token cannot reach unrelated apps. | The build environment as a secret value, one token per machine or automation runner so a single one can be revoked. Revoke and reissue in Expo account settings when a runner is retired or a token turns up somewhere it should not, such as a log or a screenshot. |
Choose how the first release reaches Play Console
Every path ends with an Android App Bundle in a Play Console track. Google requires new apps to be published as app bundles rather than APK files, and generates the per-device APKs itself. Expo documents that the default eas submit command creates a new app first release on the internal testing track, and that the app stays in draft in Play Console until the store listing and setup tasks are complete. Checked 2026-08-16. The choice below is about who does the first upload and who holds the signing keys.
| Approach | Best for | Tradeoff |
|---|---|---|
| Automated upload to the internal track from day one | Anyone who wants the same command to work on their laptop and in automation, and who is comfortable creating a service account before the first release exists. | You do the service-account setup before you see anything in Play Console, which feels like a detour on day one. It pays back on every release after the first. |
| A manual first upload in Play Console, automation afterwards | A first-time publisher who wants to see the console screens once with their own eyes before handing the job to a script. | You do the same work twice, and the manual path needs you to download the bundle and upload it by hand, which is easy to get wrong at the signing step. |
| Build locally with Android Studio, upload by hand | A team that already runs the Android toolchain and needs native modules a hosted build service does not carry. | You maintain the toolchain and the upload keystore. Losing that keystore is a real incident, though Play App Signing means it can be reset with Google rather than ending the app. |
| An app maker that publishes under its own Play developer account | Nothing you want to own. It is listed because it is what most beginners are sold first. | The listing, the install base, the reviews and the ability to move the app all belong to the vendor. You also inherit whatever their account reputation becomes. |
Recommended:Take the first option and keep your own Play Console account. Set up the service account before the first build, upload straight to the internal track, and use that track as the place you catch mistakes. Internal testing is exempt from the Data safety form, so it is the cheapest possible loop while the app is still moving.
Publish an app on Google Play
Create the Play Console account, set the app identity, upload a signed bundle to a test track, run the closed test Google counts, then apply for production access and release.
STEP 01
Create the Play Console account and choose the account type deliberately
This step decides your timeline, so read the account-type consequence before you click.
Sign up, accept the Developer Distribution Agreement, and pay the registration fee. Google lists a US$25 one-time registration fee on its Play Console help page, read on 2026-08-16, payable by credit or debit card, with prepaid cards not accepted. Confirm the current figure on that page before you budget, because a price on a blog post is exactly the kind of fact that goes stale.
Then choose Personal or Organization. A personal account created after 13 November 2023 must run a qualifying closed test before the Production track unlocks. An organization account does not carry that requirement, but it needs a real legal entity behind it, so do not invent one to skip a rule.
Complete identity verification. Google notes you may be asked for a valid government ID and a credit card, both under your legal name, and that the registration fee is not refunded if that information turns out to be invalid. New personal accounts are also asked to verify access to an Android device through the Play Console mobile app before their app can be made available. Checked 2026-08-16.
None of this depends on which tool you build the app with. The account is yours and the final release is yours to publish.
Expected result: The account exists, verification is complete, and you know from the account type whether the closed-testing gate applies to you.
Verify it: Open Play Console and look at the Production entry for a new app. If it is disabled with a note about testing requirements, the gate applies and you should start recruiting testers today.
STEP 02
Create the app record and clear the App content declarations
The declarations are a separate body of work from the app itself, and they block release independently.
Create the app with its default language, its store name, whether it is an app or a game, whether it is free or paid, and a contact email. Free or paid cannot be switched from paid to free after publishing, so decide it now.
Accept the declarations Play Console asks for at creation, including the Developer Program Policies, the US export laws declaration, and the Play App Signing terms.
Work through the App content page: privacy policy URL, ads declaration, app access instructions for anything behind a login, content rating questionnaire, target audience, data safety, and the government-app and financial-features declarations if they apply. The app access field is the Android equivalent of reviewer notes, and leaving it empty when your app has a sign-in screen is a predictable rejection.
Complete the Data safety form from what the code actually does, including data collected by any third-party library you added. Google states that developers alone are responsible for complete and accurate declarations, that it reviews the information as part of app review, and that it may take enforcement action when it becomes aware of a discrepancy between app behaviour and the declaration. Checked 2026-08-16.
Expected result: Every App content task shows as complete, and the Data safety answers match what a network trace of your app would show.
Verify it: Open the app on a device with a proxy or check your backend logs for one full session, then compare every destination and data type against the form you submitted. Any surprise in the log is a wrong answer on the form.
STEP 03
Set the application ID, version code, and target API level in the app config
Three values control identity and eligibility. The third one has a deadline attached.
The application ID is permanent once published. The version code is an integer that must increase on every upload, including uploads that get rejected. The version name is the string users see and can be anything.
Google states that starting 31 August 2026, new apps and app updates must target Android 16 (API level 36) or higher to be submitted to Google Play, with different levels for Wear OS, Automotive, TV and XR, and that an extension to 1 November 2026 can be requested. Read on 2026-08-16 from the target API level requirements page. This deadline moves every year, so check that page rather than this one before you build.
Set the minimum supported Android version honestly. Every version you support below the one you own is a version you cannot test on, and testers on old phones are how you find out.
{
"expo": {
"name": "Riverbank Bakery",
"slug": "riverbank-bakery",
"version": "1.0.0",
"android": {
"package": "com.riverbankbakery.orders",
"versionCode": 1
}
}
}Expected result: A build from this config carries the package name and version code you intended, and its target API level meets the requirement in force on the day you upload.
Verify it: Upload the bundle to the internal testing track. Play Console reports the target API level it read from the bundle, so read that number back rather than trusting your config.
STEP 04
Create the service account key and store it as a secret
The upload step authenticates to Google as a robot. That JSON file is a production credential.
Create a service account, download its JSON key, then invite that service account into Play Console and grant it release permissions for this app only. Both halves are required: a key with no Play Console invitation authenticates and then fails on permission.
Store the JSON in your build environment as a secret value. In a Playcode project the agent writes it with SetEnv marked secret, so it lands in the process environment and never in chat, code, or a committed file. Outside Playcode the equivalent rule is your CI secret store, not a file in the repository.
Leave app signing to Play App Signing, which is the default for new apps. Google holds the app signing key and you upload with an upload key. Google documents that if the upload keystore is lost or compromised you can contact Play support to reset it, which is the difference between a bad afternoon and a dead listing. Checked 2026-08-16.
{
"build": {
"production": {
"android": { "buildType": "app-bundle" }
}
},
"submit": {
"production": {
"android": {
"serviceAccountKeyPath": "./REPLACE_WITH_PATH_OUTSIDE_GIT.json",
"track": "internal"
}
}
}
}Expected result: The upload command authenticates to Play Console without an interactive prompt, and the JSON key is nowhere in the repository or the build log.
Verify it: Search the repository and the last build log for the service account email address and the private key header. Both should be absent. Confirm the key file path is covered by .gitignore.
STEP 05
Build the app bundle and upload it to the internal track
Internal testing is the cheapest loop in Play Console. Use it before anything else.
A production Android build produces an .aab. Expo documents that a build profile only produces an .apk when it sets the build type to apk, which is useful for installing on a device but cannot be submitted to Google Play. Checked 2026-08-16.
Internal testing takes up to 100 testers and builds are normally available to them within seconds of being added. It is exempt from the Data safety form requirement, so it is the right place to be while the app is still changing shape.
If you would rather upload without rolling anything out, the submit profile can mark the release as a draft and you complete it in Play Console by hand.
# Produce a signed production .aab in the cloud.
eas build --platform android --profile production
# Upload it to the track named in eas.json. For a new app this creates
# the first release on the internal testing track. It does NOT publish
# the app to Google Play.
eas submit --platform android --profile productionExpected result: The bundle appears in the internal testing track, and your internal testers can install it from the link Play Console generates.
Verify it: Install from the internal testing link on a phone that has never had the app, using a Google account that is on the tester list. If the link says the app is not available, the account is not on the list or the release is still draft.
STEP 06
Run the closed test that Google actually counts
If the gate applies to you, this step is 14 days of calendar time. Treat it as a scheduled phase, not a formality.
Google requires a closed test with at least 12 testers opted in continuously for the preceding 14 days when you apply for production access. That requirement applies to personal accounts created after 13 November 2023. Checked 2026-08-16.
Continuous is the word that catches people. Google states that testers who opt in, test for fewer than 14 days and then opt out do not count, and that if a tester opts out and opts back in, the 14 days must be consecutive. So over-recruit: aim for more than 12, and tell every one of them in writing that they must keep the app installed and stay opted in.
Give testers a specific brief and a feedback channel. You have to summarise the feedback you received, and how you collected it, in the production access application, so keep a record from day one rather than reconstructing it later.
Keep shipping to the closed track while the clock runs. Fixing bugs during the window is expected and does not reset the tester clock; opting testers out does.
Expected result: At least 12 testers have been continuously opted in for 14 consecutive days, you have a written record of their feedback, and the crashes they found are fixed.
Verify it: Read the opted-in tester count in Play Console on the day you plan to apply, not the day you invited people. Then check the testing feedback page and confirm you can write three concrete sentences about what testers reported and what you changed.
STEP 07
Apply for production access, then create the production release yourself
Production access is an application with written answers. It is reviewed by Google, and it can come back.
Apply from the Play Console dashboard. The form has three parts: how the closed test went and what testers reported, what the app is and who it is for, and how you decided it was ready for production.
Google states that review of this application usually takes seven days or less but can occasionally take longer, and that reasons for being asked to keep testing include fewer than 12 opted-in testers or insufficient tester engagement. Read on 2026-08-16. Treat that as planning guidance, not a commitment.
Answer from your record rather than from optimism. A summary that says testing went well is a weaker answer than one that names two bugs testers found and what you changed.
Once production access is granted, create the production release, choose your countries, and consider a staged rollout so a crash reaches a small percentage before it reaches everyone. The publish action is yours.
Expected result: Production access is granted and the production release is live in your chosen countries, or you have a specific reason it was declined and a plan for the next 14 days.
Verify it: Search Google Play on a device that has never had the app and open the listing. Check the developer name, the Data safety card, the screenshots and the privacy policy link, then install and complete the main task from a clean state.
STEP 08
Watch the rollout and keep the app eligible
A published Android app decays through platform deadlines rather than through neglect alone.
Watch Android vitals for crash rate and application-not-responding rate by device model and Android version, not in aggregate. Play uses these signals in distribution, and a crash concentrated on one manufacturer is invisible in an average.
Halt a staged rollout rather than pushing through it. That is the only fast reverse gear Play gives you, and it only exists while the rollout is still partial.
Diary the next target API level deadline the moment you ship. The requirement changes annually, and missing it means your update cannot be submitted and your existing app stops reaching new users on newer devices.
Keep the Data safety declaration in sync with the app. Adding an analytics library is a change to the declaration as well as to the code.
Expected result: You can name your worst device model by crash rate, your current target API level, and the date the next requirement takes effect.
Verify it: Once a quarter, open Android vitals and the target API level page on the same afternoon. If either number surprises you, the monitoring is not being read.
Four tests to run before you apply for production
These map onto the ways a Play release actually fails: a wrong declaration, a device you do not own, a duplicate write, and a reviewer who cannot sign in.
| Test | Scenario | Expected result |
|---|---|---|
| happy path | A closed tester on a phone you do not own installs from the Play link, creates an account, completes the main task, and reopens the app the next day. | The install completes on their Android version, the account is created against your production backend, the main task saves something the next session can see, and no step needs you to explain it over a message. |
| invalid input | The same tester submits the main form with a required field empty, an address with no at sign, a very long name, and text in a language your validation did not anticipate. | Each case produces a specific message on the field rather than a crash or a silent failure, and no invalid record reaches the database. |
| retry | A tester taps the main action twice on a slow connection, then loses signal mid-request and reopens the app. | One record exists, not two. The reopened app shows the completed state rather than an empty form, and the failed request offers a retry rather than a dead screen. |
| production smoke | You follow the app access instructions you wrote for Google exactly, on a device in a region and language you did not develop in, with the backend in its production configuration. | The credentials sign in first time, every destination the app contacts is one you declared on the Data safety form, and the privacy policy link inside the app opens the same live URL as the one on the listing. |
What actually goes wrong on Google Play
Half of these are account-state problems that look like technical problems. Check which one you have before you change any code.
| Symptom | Likely cause | Check | Fix |
|---|---|---|---|
| The Production track is disabled and there is no way to create a release | The closed-testing requirement for personal accounts created after 13 November 2023 has not been met, so Production and Pre-registration remain locked. | Check the account type in Play Console and its creation date, then read the current opted-in tester count on the closed test. Twelve invitations is not twelve opted-in testers. | Recruit past 12, keep them continuously opted in for 14 consecutive days, then apply for production access. There is no technical route around this and no tool can supply the testers for you. |
| The upload is rejected because the version code has already been used | A previous upload consumed that integer, including an upload that was later discarded or that failed review. | Compare the version code in your config against the highest one visible in the Play Console app bundle explorer, across every track rather than only the one you are targeting. | Increase the version code and rebuild. Automate the increment so a human never has to remember it, and never reuse a number because the previous build was never released. |
| The upload is rejected for being signed with the wrong key | The bundle was signed with a different upload key than the one Play expects for this app, usually because a second keystore was generated somewhere. | Compare the signing certificate fingerprint Play Console shows for the app against the one in the bundle you just built. Two fingerprints means two keystores. | Build with the original upload keystore. If it is genuinely lost, use the Play App Signing upload key reset path rather than creating a new listing. |
| The upload command fails to authenticate to Play Console | The service account key is valid but the service account was never invited into Play Console, or it lacks release permission on this app, or the Play Developer API is not enabled on the Cloud project. | Read the error text. An authentication failure points at the key and the Cloud project; a permission failure points at the Play Console invitation. They need opposite fixes. | Invite the service account into Play Console and grant release permission for this app, enable the API on the Cloud project, then retry. Do not widen the permission set to make an unrelated error disappear. |
| The production access application is declined and you are told to keep testing | Fewer than 12 testers were opted in at the moment you applied, testers were not continuously opted in for the preceding 14 days, or engagement was judged insufficient. | Check the opted-in count and the opt-in dates rather than the invitation dates, and reread the feedback summary you submitted. A summary with no specifics reads as a test that did not happen. | Restore the tester count, run the full window again, collect feedback you can quote, and reapply with concrete answers about what testers found and what changed. |
| The app is flagged for a Data safety declaration that does not match its behaviour | A third-party library collects or transmits something the form does not declare, or a data type was answered from intention rather than from the code. | Capture one full session of network traffic and list every destination and every field sent. Compare that list line by line against the form. Check the Play SDK Index for guidance published by each library vendor. | Correct the declaration, or remove the library if the collection is not something you want to declare. Google states developers alone are responsible for accurate declarations and that discrepancies can lead to enforcement action. |
| The update cannot be submitted because the target API level is too low | The annual target API level requirement moved past the level your build targets. | Read the target API level Play Console reports for the uploaded bundle and compare it with the requirement in force today on Google target API level requirements page. | Raise the target level, retest the permission and background behaviour changes that came with that Android version, and rebuild. If you need time, check whether an extension window is open before the deadline, not after. |
| The app works on your phone but crashes for a group of testers | A device or Android version you do not own, a manufacturer-specific behaviour, or a permission that resolves differently on a newer platform level. | Open Android vitals and segment crashes by device model and Android version. A crash concentrated on one model or one platform level is a compatibility bug, not a general instability. | Reproduce on that platform level, fix the specific incompatibility, and add at least one tester on that device family to the closed test so the next regression is caught by them rather than by the store. |
Release, watch, and keep it eligible
Deploy
Treat a release as an identified artefact: a version name, a version code, the commit it came from, the target API level, and the app access instructions that were valid when you submitted. You will need all five when a review question arrives days later.
Use a staged rollout for the first production release and for anything that touches sign-in or payments. A percentage rollout is the only reverse gear Play offers, and it stops existing once the rollout hits 100 percent.
Keep the backend the app talks to stable across a review window. An API shape that changes mid-review turns an approval into a rejection with no client change on your side.
Monitor
Read Android vitals by device model and Android version rather than in aggregate. Crash rate and application-not-responding rate feed distribution, so a concentrated problem costs more than its raw count suggests.
Watch your backend for the traffic shape the Android client creates: sign-ups from a new client, error rates on the endpoints only the app calls, and retry storms from phones with poor connections.
Track the target API level deadline as an operational date with an owner, the same way you track a certificate expiry. It is the most predictable way an otherwise healthy Android app goes stale.
Recover
Halt the staged rollout first. It is faster than any code change and it stops the blast radius growing while you diagnose.
The forward fix is a new version code, a new build and a new release. There is no way to un-ship a version that reached 100 percent, so keep the pipeline warm enough to ship a fix the same day.
Keep as much as possible changeable without a store release: server-driven configuration, feature switches and content fetched from your backend. Everything you hardcode into the bundle becomes a release cycle later.
Keys, tester data, and the declarations you sign
A Play release produces one bearer credential that can publish on your behalf and one public declaration you are accountable for. Both need the care you would give production database access.
- Treat the service account JSON key as a production credential. Store it in a secret store the build reads at run time, keep it out of the repository, and never paste it into a chat window or a URL.
- Grant the service account release permission on one app rather than account-wide access, and remove the invitation when the automation that used it is retired.
- Leave the app signing key with Play App Signing so a lost upload key is a support ticket rather than the end of the listing, and store the upload keystore itself in the same place you keep your other production secrets.
- Ship nothing sensitive inside the bundle. Anything packaged into an Android app can be extracted from a device, so API keys, admin endpoints and business rules belong on your server behind an authenticated call.
- Complete the Data safety form from observed behaviour, including data collected by third-party libraries, and update it whenever you add one. Google states you alone are responsible for complete and accurate declarations, and that it may take enforcement action on a discrepancy.
- Create the app access account you give Google as a real but disposable account with no access to other customer data, and rotate its password after each review cycle.
- Give users a way to request account and data deletion, and make the deletion real on the server rather than a flag that hides the row. Your Data safety answers and your privacy policy both describe this, so they need to be true.
Questions people ask before their first Google Play release
How much does a Google Play developer account cost?
Google lists a US$25 one-time registration fee on its Play Console help page, read on 2026-08-16, payable by credit or debit card, with prepaid cards not accepted and card types varying by location. It is a one-time fee rather than an annual one. Check that page for the current figure before you budget rather than trusting a number on any blog, including this one.
Do I really need 12 testers for 14 days to publish on Google Play?
Only for some accounts. Google requires developers with personal accounts created after 13 November 2023 to run a closed test with at least 12 testers opted in continuously for the preceding 14 days before they can apply for production access. Organization accounts, and personal accounts created on or before that date, are not subject to it. Checked 2026-08-16. Check your own account type in Play Console rather than assuming.
What counts as a continuously opted-in tester?
Someone who joins the closed test and stays in it. Google states that testers who opt in, test for fewer than 14 days and then opt out do not count, and that if a tester opts out and opts back in, the 14 days must be consecutive. Recruit more than 12 and tell each person in writing to keep the app installed for the whole window.
What is the Google Play Data safety section?
It is a form in Play Console that becomes the public data card on your listing. Every developer with a published app must complete it, including apps on closed, open and production tracks, and including apps that collect no data, which still need a privacy policy link. Apps active only on the internal testing track are exempt. Checked 2026-08-16.
How long does Google Play review take?
For the production access application, Google states review usually takes seven days or less but can occasionally take longer, read on 2026-08-16. App review itself varies by app and by what you changed. Plan in days, add slack for a rejection, and treat any duration quoted here or elsewhere as planning guidance rather than a service commitment.
Does Google Play approval mean my app is secure and private?
No. Play review checks policy adherence. Google states that developers alone are responsible for complete and accurate Data safety declarations and that it cannot determine on your behalf how you handle user data, and that review is not a troubleshooting step for a non-compliant app. Approval is not a privacy, security, accessibility or quality certification, and you should not describe it as one.
Can Playcode publish my app to Google Play for me?
No. Playcode can build the Android app, run the cloud build and the upload from your project, and draft the store listing copy and screenshots. The Play Console account is yours, the closed test is yours to run, and you create the production release yourself. The developer account requirement is not something a tool can absorb.
Do I have to upload an app bundle instead of an APK?
Yes for new apps. Google requires new apps to be published as Android App Bundles rather than APK files and generates optimised APKs per device from the bundle. Expo documents that a build profile which forces an APK output cannot be submitted to Google Play, which is why the production build profile produces a bundle by default. Checked 2026-08-16.
Build it on Playcode
Build the Android app and the backend it needs in one project
Playcode builds a React Native app beside its own backend and database, so someone who signed up on your website can sign in on the phone. The agent runs the cloud build and the store upload from the project, and drafts the listing copy and screenshots. Your Play Console account stays yours, and you create the production release.
Start Building My AppNo credit card required. The Google Play registration fee is separate and paid to Google.