The SafetyNet Attestation API helps you assess the security and compatibility of the Android environments in which your apps run. You can use this API to analyze devices that have installed your app.
SafetyNet examines software and hardware information on the device where your app is installed to create a profile of that device. The service then attempts to find this same profile within a list of device models that have passed Android compatibility testing. The API also uses this software and hardware information to help you assess the basic integrity of the device, as well as the APK information of the calling app. This attestation helps you to determine whether or not the particular device has been tampered with or otherwise modified. It also assesses the trustworthiness of the app that is requesting information from your backend logic.
Ideally, you should use the SafetyNet Attestation API as an additional in-depth defense signal as part of an anti-abuse system, rather than the sole anti-abuse signal for your app.
This document shows you how to use the SafetyNet APIs to request a compatibility check and how to verify the response that the API provides.
Note: To see an Android app that contains a complete implementation of the SafetyNet Attestation API, see the SafetyNet API sample on GitHub. You can use this sample to learn more about how to verify devices' integrity from your app.
Additional Terms of Service
By accessing or using the SafetyNet APIs, you agree to the Google APIs Terms of Service, and to these Additional Terms. Please read and understand all applicable terms and policies before accessing the APIs.
SafetyNet Terms of Service
As with any data collected in large volume from in-the-field observation, there is a chance of both false positives and false negatives. We are presenting the data to the best of our understanding. We extensively test our detection mechanisms to ensure accuracy, and we are committed to improving those methods over time to ensure they continue to remain accurate.
You agree to comply with all applicable law, regulation, and third party rights (including without limitation laws regarding the import or export of data or software, privacy, and local laws). You will not use the APIs to encourage or promote illegal activity or violation of third party rights. You will not violate any other terms of service with Google (or its affiliates).
You acknowledge and understand that the SafetyNet API works by collecting hardware and software information, such as device and application data and the results of integrity checks, and sending that data to Google for analysis. Pursuant to Section 3(d) of the Google APIs Terms of Service, you agree that if you use the APIs that it is your responsibility to provide any necessary notices or consents for the collection and sharing of this data with Google.
Connect to Google Play services
The SafetyNet API is part of Google Play services. To connect to the API, you need to create an instance of the Google Play services API client. You can then use the Google API client classes to connect to the SafetyNet API.
To connect to the API, in your activity's onCreate()
method, create an instance of Google API Client using
GoogleApiClient.Builder. Use the builder to add the SafetyNet
API, as shown in the following code example:
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(SafetyNet.API)
.addConnectionCallbacks(myMainActivity.this)
.build();
}
Note: You can only call these methods after your app has
established a connection to Google Play services by receiving the
onConnected() callback. For details about listening for a
completed client connection, see Accessing Google APIs.
Adding an API Key to the Manifest
To provide your apps with enough capacity, and to minimize throttling and latency, we recommend that you use an API key.
To get an API key for the Android Device Verification API, complete the following steps:
- Go to the Google Developers Console.
- Select a project, or create a new one.
- In the sidebar on the left, expand APIs & auth, then click APIs. In the list of APIs, make sure that all of the APIs you are using show a status of ON.
- In the Browse APIs list, find the Android Device Verification API and turn it on.
- Obtain your API key by expanding APIs & auth and clicking Credentials. Record the API KEY (not the Android Key) value on this page for later use.
In your app's manifest file, add the API key that you just obtained using the Google Developers Console:
<application>
<meta-data android:name="com.google.android.safetynet.ATTEST_API_KEY"
android:value="YOUR_API_KEY">
<activity>
...
</activity>
</application>
Requesting a Compatibility Check
A SafetyNet compatibility check allows your app to check if the device running your app has passed Android compatibility testing and whether your app has been modified by an unknown source. The compatibility check creates a device profile by gathering information about the device's hardware and software characteristics, including the platform build.
To perform a check using the API, you need to complete a few implementation steps in your app. After you have established a connection to Google Play services and have requested the SafetyNet API from the Google API client, your app can then perform the following steps to use the service:
- Obtain a single use token
- Send the compatibility check request
- Read the response
- Validate the response
For more information about Android compatibility testing, see Android Compatibility and the Compatibility Testing Suite (CTS).
Because SafetyNet checks use network resources, the speed of responses to requests can vary, depending on a device's network connection status. The code described in this section should be executed outside of your app's main execution thread to avoid pauses and unresponsiveness in your app's user interface. For more information about using separate execution threads, see Sending Operations to Multiple Threads.
Obtain a single use token
The SafetyNet API uses security techniques to help you verify the integrity of the communications between your app and the service. When you request a compatibility check, you must provide a single use token in the form of a number used once, or nonce, as part of your request. A nonce is a random token generated in a cryptographically secure manner.
You can obtain a nonce by generating one within your app each time you make a compatibility check request. As a more secure option, you can obtain a nonce from your own server, using a secure connection.
A nonce used with a SafetyNet request should be at least 16 bytes in length. You should introduce variability in your nonce, and you should derive part of the nonce from the data you're sending to the server. For example, you could concatenate the hash of the username with the request timestamp to form the nonce.
After you make a check request, the response from the SafetyNet service includes your nonce, so you can verify it against the one you sent. As the name indicates, you should only use a nonce value once, for a single check request. Use a different nonce for any subsequent check requests.
For additional guidelines on using cryptography functions, see Security Tips.
Send the compatibility check request
After you have established a connection to Google Play services and have created a nonce, you're ready to make a compatibility check request. Because the response to your request may not be immediate, you set up a callback listener to handle the response from the service, as shown in the following code example:
byte[] nonce = getRequestNonce(); // Should be at least 16 bytes in length.
SafetyNet.SafetyNetApi.attest(mGoogleApiClient, nonce)
.setResultCallback(new ResultCallback<SafetyNetApi.AttestationResult>() {
@Override
public void onResult(SafetyNetApi.AttestationResult result) {
Status status = result.getStatus();
if (status.isSuccess()) {
// Indicates communication with the service was successful.
// Use result.getJwsResult() to get the result data.
} else {
// An error occurred while communicating with the service.
}
}
});
The
isSuccess() method indicates whether or not communication
with the service was successful, but it doesn't indicate if the device has
passed the compatibility check. The next section discusses how to read the
check result and verify its integrity.
Read the compatibility check response
When your app communicates with SafetyNet, the service provides a response
containing the result of the compatibility check and includes additional information to help you verify the
integrity of the message. The result is provided as a
AttestationResult object. Use the
getJwsResult() method of this object to obtain the data of
the request. The response is formatted as a JSON Web Signature (JWS). The following JWS excerpt
shows the format of the payload data:
{
"nonce": "R2Rra24fVm5xa2Mg",
"timestampMs": 9860437986543,
"apkPackageName": "com.package.name.of.requesting.app",
"apkCertificateDigestSha256": ["base64 encoded, SHA-256 hash of the
certificate used to sign requesting app"],
"apkDigestSha256": "base64 encoded, SHA-256 hash of the app's APK",
"ctsProfileMatch": true,
"basicIntegrity": true,
}
The contents of the JWS message depend on the scenario:
-
If the value of
"ctsProfileMatch"istrue, then the profile of the device running your app matches the profile of a device that has passed Android compatibility testing. -
If the value of
"basicIntegrity"istrue, then the device running your app likely wasn't tampered with, but the device has not necessarily passed Android compatibility testing.Note: The
"basicIntegrity"field is a weaker check than"ctsProfileMatch". For apps requiring stronger checks, use only the result from"ctsProfileMatch". -
The
"apkPackageName","apkCertificateDigestSha256", and"apkDigestSha256"fields provide information about the APK that you can use to verify the identity of the calling app. These fields are absent if the API cannot reliably determine the APK information.
Error cases
The JWS message can also show several types of error conditions:
-
A
nullresult indicates that the call to the service didn't complete successfully. -
An
"error"field indicates that an issue, usually a network error, occurred when completing the verification process. When performing retry requests, you should use an exponential backoff technique to avoid sending too many requests to the service.
Verify the compatibility check response
You should take steps to make sure that the compatibility check response actually came from the SafetyNet service and includes data that matches your request data.
Caution: You should send the entire JWS response to your own server, using a secure connection, for verification. We don't recommend that you perform the verification directly in your app because, in that case, there is no guarantee that the verification logic itself hasn't been modified.
Follow these steps to verify the origin of the JWS message:
- Extract the SSL certificate chain from the JWS message.
- Validate the SSL certificate chain and use SSL hostname matching to verify
that the leaf certificate was issued to the hostname
attest.android.com. - Use the certificate to verify the signature of the JWS message.
- Check the data of the JWS message to make sure it matches the data within your original request. In particular, make sure that the nonce, timestamp, package name, and the SHA-256 hashes match.
Validating the response with Google APIs
You should verify the JWS statement using the standard crytographic solutions found in the SafetyNet samples on GitHub. For cases where this is inconvenient, such as during early testing, Google provides an Android Device Verification API for verifying the JWS statement.
Note: You need an API key to access the Android Device Verification API, and the API is rate-limited. For these reasons, you should use the API only for testing during the initial development stage. You shouldn't use this verification API in a production scenario.
Important: This use of the Android Device Verification API only validates that the provided JWS message was received from the SafetyNet service. It doesn't verify that the payload data matches the data within your original compatibility check request.
After enabling this API for your project, you can call the verification service from your app or server. You need the contents of the JWS message from the SafetyNet API and your API key to call the verification API and get a result.
To use the Android Device Verification API, complete the following steps:
-
Create a JSON message containing the entire contents of the JWS message. Use
the following format:
{ "signedAttestation": "<output of getJwsResult()>" } -
Use an HTTP POST request to send the message with a Content-Type of
"application/json"to the following URL:https://www.googleapis.com/androidcheck/v1/attestations/verify?key=<your API key>
-
The service validates the integrity of the message. If the message is valid,
it returns a JSON message with the following contents:
{ "isValidSignature": true }
Samples
For additional guidance on working with the SafetyNet APIs, view the samples that are available on GitHub.


