---
title: "Call Firebase Cloud Functions from a Capacitor App"
description: Call Firebase Cloud Functions from a Capacitor app to run serverless backend logic — callable functions, automatic auth, error handling, and local testing.
date:
  created: 2026-09-05
  updated: 2026-09-05
authors:
  - djabif
categories:
  - Capacitor
  - Firebase
  - Guides
  - SDKs
links:
  - Capacitor Firebase Cloud Functions: sdks/capacitor/firebase/cloud-functions.md
faq: true
---

# Call Firebase Cloud Functions from a Capacitor App

Some logic has no business running on the client: charging a card, granting a role, anything that trusts a value the user could tamper with. [Firebase Cloud Functions](https://firebase.google.com/docs/functions/){:target="_blank"} let you run that code on Google's servers instead, and the [Capacitor Firebase Cloud Functions plugin](../../sdks/capacitor/firebase/cloud-functions.md) lets your app invoke it with a single call. There are no endpoints to wire up and no auth headers to attach by hand.

This guide covers the full round trip: writing and deploying a callable function, installing and configuring the plugin, calling functions by name or URL, handling the auth and errors that come back, and testing against the local emulator before you deploy.

<!-- more -->

<div class="capawesome-z29o10a">
  <a href="/" target="_blank">
    <img alt="Build and deploy your Capacitor app with Capawesome Cloud" src="https://capawesome.io/assets/banners/cloud-build-and-deploy-capacitor-apps.png?t=1" />
  </a>
</div>

## Key Takeaways

- The plugin calls callable functions (`onCall`), not raw HTTP (`onRequest`) endpoints. Callable functions handle serialization, CORS, and token attachment for you.
- A callable function automatically receives the caller's Firebase Auth token and App Check token, so `request.auth` is populated server-side without you attaching anything.
- Call a function with [`callByName(...)`](../../sdks/capacitor/firebase/cloud-functions.md#callbyname), or [`callByUrl(...)`](../../sdks/capacitor/firebase/cloud-functions.md#callbyurl) for a custom domain or non-default region.
- You can pass and return any JSON-serializable data: strings, numbers, booleans, arrays, and objects.
- Errors thrown as `HttpsError` on the server arrive client-side with a `code` and `message` you can handle.
- Test locally with [`useEmulator(...)`](../../sdks/capacitor/firebase/cloud-functions.md#useemulator). On an Android emulator, reach your host machine at `10.0.2.2`.

## How to Call a Firebase Cloud Function from a Capacitor App

Calling a Firebase Cloud Function from a Capacitor app takes four steps:

1. **Deploy a callable function** (`onCall`) to your Firebase project.
2. **Install** `@capacitor-firebase/functions` and sync the native projects.
3. **Add the native config files** so the plugin can reach your project.
4. **Call the function** with `callByName()` and read the result. Auth and App Check tokens ride along automatically.

The following sections break each step down, then get into error handling, the emulator, best practices, and troubleshooting.

## What Are Firebase Cloud Functions?

[Firebase Cloud Functions](https://firebase.google.com/docs/functions/){:target="_blank"} run your backend code on Google's infrastructure, triggered by an HTTPS call or a Firebase event, with no server to provision or scale. The [Capacitor Firebase Cloud Functions plugin](../../sdks/capacitor/firebase/cloud-functions.md) exposes the native Android and iOS Functions SDKs, plus the Firebase JS SDK on web, behind one shared TypeScript API.

The plugin calls *callable* functions, not raw HTTP functions. A callable function (`onCall`) is built to be invoked from a Firebase client SDK. It automatically deserializes your data, attaches the user's auth and App Check tokens, and handles CORS. A plain HTTP function (`onRequest`) is a bare endpoint you'd hit with `fetch` and wire up yourself. This plugin is for the former. If you have an `onRequest` function, call it with `fetch` (or `callByUrl` if it's a callable exposed at a URL), not `callByName`.

## Why Call Cloud Functions from a Capacitor App?

Common cases for the plugin:

- **Serverless backend logic.** Run trusted server-side code that must not live in the client: payments, privileged writes, third-party API calls with secret keys.
- **Structured data exchange.** Pass strings, numbers, booleans, arrays, and objects to a function and process the result it returns.
- **Custom domains and regions.** Call a function deployed to a specific region or a custom domain by its URL.
- **Local development.** Test against the Cloud Functions emulator before deploying to production.

## Before You Start

To follow along you'll need three things: a Capacitor app with the `android` and/or `ios` platforms added, a Firebase project, and the [Firebase CLI](https://firebase.google.com/docs/cli){:target="_blank"} for deploying functions. Cloud Functions requires the Firebase Blaze (pay-as-you-go) plan, which has a free tier but does need a billing account.

## Step 1: Deploy a Callable Function

The plugin is the client half; you also need a function to call. A minimal callable function that reads the caller's data and their auth state looks like this:

```javascript
// functions/index.js
const { onCall, HttpsError } = require('firebase-functions/v2/https');

exports.getGreeting = onCall(request => {
  if (!request.auth) {
    throw new HttpsError('unauthenticated', 'You must be signed in.');
  }
  const name = request.data.name ?? 'there';
  return { message: `Hello, ${name}!` };
});
```

Deploy it with the Firebase CLI:

```bash
firebase deploy --only functions
```

Note two things you'll rely on from the client: `request.auth` is populated automatically for signed-in users (no token handling on your side), and errors are thrown as `HttpsError` so they arrive on the client with a recognizable code.

## Step 2: Install the Plugin

Install the plugin and sync the native projects:

```bash
npm install @capacitor-firebase/functions
npx cap sync
```

## Step 3: Add Firebase to Your Native Apps

Add the native config files Firebase generates ([full reference](https://github.com/capawesome-team/capacitor-firebase/blob/main/docs/firebase-setup.md){:target="_blank"}): `google-services.json` in `android/app/`, and `GoogleService-Info.plist` added to the Xcode project in `ios/App/App/`. If you target the web platform, initialize the Firebase JS SDK with your web app's config.

If your iOS project uses Swift Package Manager, configure the `symlink` package option in `capacitor.config.ts` (Capacitor CLI 8.4.0+) to sidestep a SwiftPM package identity collision:

```json
{
  "experimental": {
    "ios": {
      "spm": {
        "packageOptions": {
          "@capacitor-firebase/functions": { "symlink": true }
        }
      }
    }
  }
}
```

The plugin itself needs no additional configuration.

## Calling a Function by Name

Invoke a callable function with [`callByName(...)`](../../sdks/capacitor/firebase/cloud-functions.md#callbyname). Whatever you pass in `data` is delivered to the function, and its return value comes back in the `data` property:

```typescript
import { FirebaseFunctions } from '@capacitor-firebase/functions';

const getGreeting = async (name: string) => {
  const { data } = await FirebaseFunctions.callByName({
    name: 'getGreeting',
    data: { name },
  });
  return data; // { message: 'Hello, Dayana!' }
};
```

If your function is deployed to a region other than the default, pass the `region` option so the SDK reaches the right endpoint:

```typescript
import { FirebaseFunctions } from '@capacitor-firebase/functions';

const callInRegion = async () => {
  const { data } = await FirebaseFunctions.callByName({
    name: 'getGreeting',
    data: { name: 'Dayana' },
    region: 'europe-west1',
  });
  return data;
};
```

## Calling a Function by URL

For a function on a custom domain, or when you'd rather address it directly, use [`callByUrl(...)`](../../sdks/capacitor/firebase/cloud-functions.md#callbyurl):

```typescript
import { FirebaseFunctions } from '@capacitor-firebase/functions';

const callByUrl = async () => {
  const { data } = await FirebaseFunctions.callByUrl({
    url: 'https://europe-west1-your-project.cloudfunctions.net/getGreeting',
    data: { name: 'Dayana' },
  });
  return data;
};
```

## Auth and App Check Ride Along Automatically

When you call a callable function, the plugin automatically attaches the current user's Firebase Auth token and, if you've set it up, the App Check token. You don't build headers or pass a token yourself. On the server, that's why `request.auth` is populated for a signed-in user.

The catch is that "signed-in" means signed in through the [Capacitor Firebase Authentication plugin](./capacitor-firebase-authentication-guide.md), since the Functions and Authentication SDKs share the same native session. If a call arrives with an empty `request.auth`, the user isn't authenticated on the native layer. Check your sign-in flow before assuming the function is wrong. To also require that the call comes from your genuine app, set up [App Check](./capacitor-firebase-app-check-guide.md) and enforce it on Cloud Functions; the token is attached to callable requests automatically.

## Handling Errors From a Function

An `HttpsError` thrown on the server arrives on the client as a rejected promise carrying its `code` and `message`, so a plain `try/catch` gives you structured errors instead of a generic failure:

```typescript
import { FirebaseFunctions } from '@capacitor-firebase/functions';

const getGreeting = async (name: string) => {
  try {
    const { data } = await FirebaseFunctions.callByName({
      name: 'getGreeting',
      data: { name },
    });
    return data;
  } catch (error) {
    // error.message carries the HttpsError message, e.g. "You must be signed in."
    console.error('Function call failed:', error);
    throw error;
  }
};
```

Throw specific `HttpsError` codes (`unauthenticated`, `permission-denied`, `invalid-argument`, and so on) on the server rather than letting an unhandled exception bubble up. An unhandled error is reported to the client as a generic `internal` error with no useful detail.

## Testing Against the Local Emulator

Point the plugin at the [Cloud Functions emulator](https://firebase.google.com/docs/functions/local-emulator){:target="_blank"} during development so you're not deploying on every change. The emulator listens on port 5001 unless your `firebase.json` overrides it, and on an Android emulator, `10.0.2.2` is the special address that reaches your host machine's `localhost`:

```typescript
import { FirebaseFunctions } from '@capacitor-firebase/functions';

const connectToEmulator = async () => {
  await FirebaseFunctions.useEmulator({
    host: '10.0.2.2',
    port: 5001,
  });
};
```

Reaching the emulator over plain HTTP means Android must allow cleartext traffic, which you enable only for debug builds. Never ship it in production.

## Cloud Functions Best Practices

### Do the Trust-Sensitive Work in the Function, Not the Client

The whole point of a callable function is that the client can't be trusted with certain logic. Verify permissions, validate inputs, and read secrets inside the function. Never send an "isAdmin: true" flag from the app and believe it.

### Check `request.auth` on the Server

Because auth is attached automatically, it's easy to forget the function still has to *check* it. Guard privileged functions with an explicit `request.auth` check and throw `unauthenticated` or `permission-denied`, rather than assuming only signed-in users can reach the function.

### Set the Region Once, Consistently

If your functions live in a non-default region, a call without the matching `region` resolves the wrong (or nonexistent) endpoint and fails. Centralize the region in one place in your app so every call uses it.

### Keep Payloads Small

Callable functions serialize their data as JSON over the wire. Send identifiers and the minimum a function needs, not large blobs. For files, upload to [Cloud Storage](./capacitor-firebase-cloud-storage-guide.md) and pass the path instead.

## Common Errors and Troubleshooting

- **`request.auth` is null on the server.** The user isn't signed in on the native layer. Confirm sign-in works through the [Capacitor Firebase Authentication plugin](./capacitor-firebase-authentication-guide.md). The Functions SDK reads that same session.
- **The call fails with a generic `internal` error.** The function threw an unhandled exception. Throw a specific `HttpsError` on the server so the client gets a real code and message.
- **A call to a non-default region times out or 404s.** Pass the `region` option to `callByName(...)`, or address the function with `callByUrl(...)`.
- **The emulator is unreachable on Android.** Use `10.0.2.2` (not `localhost`) as the host, and make sure cleartext traffic is allowed for your debug build.
- **`fetch`-style CORS errors.** You're treating a callable function like a raw HTTP endpoint. Use `callByName(...)`/`callByUrl(...)`. Callable functions handle CORS; `onRequest` functions don't.
- **App crashes on launch.** The `google-services.json` / `GoogleService-Info.plist` file is missing or misplaced (Step 3).

## FAQ

### What's the difference between `callByName` and `callByUrl`?

[`callByName(...)`](../../sdks/capacitor/firebase/cloud-functions.md#callbyname) calls a callable function by its name (and optional region), which is what you'll use most of the time. [`callByUrl(...)`](../../sdks/capacitor/firebase/cloud-functions.md#callbyurl) calls it by its full URL instead, which is useful when the function is hosted on a custom domain.

### Can this plugin call HTTP (`onRequest`) functions, not just callable ones?

No. The plugin is built for callable functions (`onCall`), which automatically handle data serialization, CORS, and attaching the auth and App Check tokens. For a raw HTTP `onRequest` endpoint, use a normal HTTP request with a library like `fetch` and handle those concerns yourself.

### Do I need to attach the user's auth token myself?

No. Callable functions automatically include the signed-in user's Firebase Auth token and the App Check token, so `request.auth` is populated on the server without any header handling on your side, as long as the user is signed in through the Capacitor Firebase Authentication plugin.

### How do I test my Cloud Functions locally?

Use [`useEmulator(...)`](../../sdks/capacitor/firebase/cloud-functions.md#useemulator) to point the app at the local Cloud Functions emulator. On an Android emulator, use `10.0.2.2` as the host to reach your computer's `localhost`, and allow cleartext traffic in your debug build only.

## Turn Backend Changes Into Same-Day Releases

Your app's calls to Cloud Functions live in the web layer, so adjusting how you call a function (a new parameter, a changed flow, a fixed error path) is a web-layer change that doesn't need an app store review. [Capawesome Cloud](https://capawesome.io/){:target="_blank"} builds your iOS and Android apps in the cloud and ships those changes over the air with live updates, so your client can keep pace with your backend, and it automates App Store and Play Store submission when a native release is needed.

[Try Capawesome Cloud Free](https://capawesome.io){ .md-button .md-button--primary }

## Conclusion

Move a piece of logic into a callable function when the client can't be trusted with it, and leave it in the app when it can. Once it's on the server, reach for `callByName(...)` by default, add the `region` option (or switch to `callByUrl(...)`) only when the function isn't in the default region, and open every privileged function with an explicit `request.auth` check. The plugin attaching the token is not the same as your function verifying it.

If you want to go deeper from here:

- [Firebase Authentication in Capacitor: Setup & Best Practices](./capacitor-firebase-authentication-guide.md) covers the sign-in that populates `request.auth` in your callable functions.
- [Firebase App Check in a Capacitor App](./capacitor-firebase-app-check-guide.md) shows how to require that calls to your functions come from your genuine app.
- [Capacitor Firestore: Real-Time Data & Offline Sync](./capacitor-firebase-cloud-firestore-guide.md) covers the database a callable function often reads or writes on the user's behalf.

Stuck on a callable that won't behave? Bring it to the [Capawesome Discord server](https://discord.gg/VCXxSVjefW){:target="_blank"}, and subscribe to the [Capawesome newsletter](https://capawesome.io/newsletter/){:target="_blank"} to catch the next guide when it lands.
