Protect custom backend resources with App Check in web apps
Stay organized with collections
Save and categorize content based on your preferences.
You can use App Check to protect non-Google custom backend resources for
your app, like your own self-hosted backend. To do so, you'll need to do both of
the following:
Modify your app client to send an App Check token along with each request
to your backend, as described on this page.
In your app client, before each request, get a valid, unexpired, App Check
token with appCheck().getToken(). The App Check library will refresh the
token if necessary.
Once you have a valid token, send it along with the request to your backend. The
specifics of how you accomplish this are up to you, but don't send
App Check tokens as part of URLs, including in query parameters, as this
makes them vulnerable to accidental leakage and interception. The following
example sends the token in a custom HTTP header, which is the recommended
approach.
Web
import{initializeAppCheck,getToken}from'firebase/app-check';constappCheck=initializeAppCheck(app,{provider:provider}// ReCaptchaV3Provider or CustomProvider);constcallApiWithAppCheckExample=async()=>{letappCheckTokenResponse;try{appCheckTokenResponse=awaitgetToken(appCheck,/* forceRefresh= */false);}catch(err){// Handle any errors if the token was not retrieved.return;}// Include the App Check token with requests to your server.constapiResponse=awaitfetch('https://yourbackend.example.com/yourApiEndpoint',{headers:{'X-Firebase-AppCheck':appCheckTokenResponse.token,}});// Handle response from your backend.};
constcallApiWithAppCheckExample=async()=>{letappCheckTokenResponse;try{appCheckTokenResponse=awaitfirebase.appCheck().getToken(/* forceRefresh= */false);}catch(err){// Handle any errors if the token was not retrieved.return;}// Include the App Check token with requests to your server.constapiResponse=awaitfetch('https://yourbackend.example.com/yourApiEndpoint',{headers:{'X-Firebase-AppCheck':appCheckTokenResponse.token,}});// Handle response from your backend.};
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-08-27 UTC."],[],[],null,["You can use App Check to protect non-Google custom backend resources for\nyour app, like your own self-hosted backend. To do so, you'll need to do both of\nthe following:\n\n- Modify your app client to send an App Check token along with each request to your backend, as described on this page.\n- Modify your backend to require a valid App Check token with every request, as described in [Verify App Check tokens from a custom backend](/docs/app-check/custom-resource-backend).\n\nBefore you begin\n\nAdd App Check to your app, using either the\n[reCAPTCHA Enterprise provider](/docs/app-check/web/recaptcha-enterprise-provider)\nor a [custom provider](/docs/app-check/web/custom-provider).\n\nSend App Check tokens with backend requests\n\nIn your app client, before each request, get a valid, unexpired, App Check\ntoken with `appCheck().getToken()`. The App Check library will refresh the\ntoken if necessary.\n\nOnce you have a valid token, send it along with the request to your backend. The\nspecifics of how you accomplish this are up to you, but *don't send\nApp Check tokens as part of URLs*, including in query parameters, as this\nmakes them vulnerable to accidental leakage and interception. The following\nexample sends the token in a custom HTTP header, which is the recommended\napproach. \n\nWeb \n\n```javascript\nimport { initializeAppCheck, getToken } from 'firebase/app-check';\n\nconst appCheck = initializeAppCheck(\n app,\n { provider: provider } // ReCaptchaV3Provider or CustomProvider\n);\n\nconst callApiWithAppCheckExample = async () =\u003e {\n let appCheckTokenResponse;\n try {\n appCheckTokenResponse = await getToken(appCheck, /* forceRefresh= */ false);\n } catch (err) {\n // Handle any errors if the token was not retrieved.\n return;\n }\n\n // Include the App Check token with requests to your server.\n const apiResponse = await fetch('https://yourbackend.example.com/yourApiEndpoint', {\n headers: {\n 'X-Firebase-AppCheck': appCheckTokenResponse.token,\n }\n });\n\n // Handle response from your backend.\n};https://github.com/firebase/snippets-web/blob/467eaa165dcbd9b3ab15711e76fa52237ba37f8b/snippets/appcheck-next/index/appcheck_nonfirebase.js#L8-L32\n```\n\nWeb \n\n```javascript\nconst callApiWithAppCheckExample = async () =\u003e {\n let appCheckTokenResponse;\n try {\n appCheckTokenResponse = await firebase.appCheck().getToken(/* forceRefresh= */ false);\n } catch (err) {\n // Handle any errors if the token was not retrieved.\n return;\n }\n\n // Include the App Check token with requests to your server.\n const apiResponse = await fetch('https://yourbackend.example.com/yourApiEndpoint', {\n headers: {\n 'X-Firebase-AppCheck': appCheckTokenResponse.token,\n }\n });\n\n // Handle response from your backend.\n};https://github.com/firebase/snippets-web/blob/467eaa165dcbd9b3ab15711e76fa52237ba37f8b/appcheck/index.js#L68-L85\n```\n\nReplay protection (beta)\n\nWhen making a request to an endpoint for which you've enabled\n[replay protection](/docs/app-check/custom-resource-backend#replay-protection),\nacquire a token using `getLimitedUseToken()` instead of `getToken()`: \n\n import { getLimitedUseToken } from \"firebase/app-check\";\n\n // ...\n\n appCheckTokenResponse = await getLimitedUseToken(appCheck);"]]