---
title: Declare your app's network access
description: >-
  List the external hosts that your app links customers to and the servers that
  your app's code loads from or sends requests to, so Shopify can protect your
  app.
source_url:
  html: >-
    https://shopify.dev/docs/apps/build/security/storefront/declare-network-access
  md: >-
    https://shopify.dev/docs/apps/build/security/storefront/declare-network-access.md
---

# Declare your app's network access

Declare the external hosts and servers that your app uses in the [`network_access`](https://shopify.dev/docs/apps/build/cli-for-apps/app-configuration#network_access) section of your app configuration file.

***

## Why

Your app's code runs on pages that merchants and customers trust: storefronts, checkout, and the Shopify admin. When you declare the hosts and servers that your app uses, Shopify knows what your app's links and requests should look like. We use the list to protect your app and monitor storefronts for malicious requests.

Declaring the hosts that your app links to also improves the customer experience. Shopify skips the exit interstitial for links from an online store to those hosts.

***

## How

* List every external host that your app links customers to from the online store in `allowed_navigation_hosts`. Only list hosts that you control, such as your app's own domain.
* List every external server that your app's code loads from or sends requests to in `allowed_sources`. This covers your [extensions](https://shopify.dev/docs/apps/build/app-extensions) and the pages that your app serves, such as your [app home](https://shopify.dev/docs/apps/build/app-home) and HTML or Liquid [app proxy](https://shopify.dev/docs/apps/build/online-store/app-proxies) pages.
* Leave out anything that Shopify serves, such as the files in a theme app extension's `assets` folder. Leave out your app proxy URL too: the store serves app proxy pages from its own domain.

***

## Examples

The following examples show code from three parts of an app, and the `network_access` entries that each one needs. The code is on the left, and the entries that it adds are on the right.

### Theme app extension

This app block links to the app's review page, loads a widget from the app's CDN, and fetches reviews from the app's API. The block's own `reviews.js` file is in the extension's `assets` folder, so Shopify serves it and it doesn't need an entry.

## extensions/reviews/blocks/reviews.liquid

```liquid
<div id="reviews" data-product-id="{{ product.id }}"></div>


<a href="https://app.example.com/reviews/{{ product.handle }}">
  Read all reviews
</a>


<script src="https://cdn.app.example.com/widget.js" defer></script>
<script src="{{ 'reviews.js' | asset_url }}" defer></script>


{% schema %}
{
  "name": "Product reviews",
  "target": "section"
}
{% endschema %}
```

## extensions/reviews/assets/reviews.js

```js
const container = document.getElementById('reviews');


fetch(`https://api.app.example.com/reviews?product_id=${container.dataset.productId}`)
  .then((response) => response.json())
  .then((reviews) => renderReviews(container, reviews));
```

## shopify.app.toml

```toml
[network_access]
# The "Read all reviews" link
allowed_navigation_hosts = ["app.example.com"]
allowed_sources = [
  # The widget script
  "https://cdn.app.example.com",
  # The fetch in reviews.js
  "https://api.app.example.com",
]
```

### App proxy page

This [app proxy](https://shopify.dev/docs/apps/build/online-store/app-proxies) route renders a Liquid page in the store's theme. The page links to the app's help center and loads the same widget. The store serves the page from its own domain, so the app proxy URL itself doesn't need an entry.

## app/routes/apps.reviews.tsx

```ts
import {authenticate} from '~/shopify.server';


export async function loader({request}) {
  const {liquid} = await authenticate.public.appProxy(request);


  return liquid(`
    <h1>Reviews for {{ shop.name }}</h1>
    <div id="reviews"></div>
    <a href="https://help.app.example.com/reviews">How reviews work</a>
    <script src="https://cdn.app.example.com/widget.js" defer></script>
  `);
}
```

## shopify.app.toml

```toml
[network_access]
# The "How reviews work" link
allowed_navigation_hosts = ["help.app.example.com"]
# The widget script
allowed_sources = ["https://cdn.app.example.com"]
```

### Checkout UI extension

This checkout UI extension fetches the customer's loyalty points from the app's API. To call `fetch()`, a checkout UI extension also needs the [`network_access` capability](https://shopify.dev/docs/apps/build/checkout/capabilities#network-access) in its own `shopify.extension.toml` file. That capability is separate from the app's `[network_access]` section.

## extensions/loyalty/src/Checkout.jsx

```jsx
import '@shopify/ui-extensions/preact';
import {render} from 'preact';
import {useEffect, useState} from 'preact/hooks';


export default function extension() {
  render(<Extension />, document.body);
}


function Extension() {
  const [points, setPoints] = useState(null);


  useEffect(() => {
    async function loadPoints() {
      const token = await shopify.sessionToken.get();
      const response = await fetch('https://api.app.example.com/loyalty', {
        headers: {Authorization: `Bearer ${token}`},
      });
      const data = await response.json();
      setPoints(data.points);
    }


    loadPoints();
  }, []);


  if (points === null) return null;


  return <s-banner>You have {points} loyalty points.</s-banner>;
}
```

## shopify.app.toml

```toml
[network_access]
# The fetch to the loyalty API
allowed_sources = ["https://api.app.example.com"]
```

### Complete configuration

List each host and source once, however many parts of your app use it. Together, the three examples need this configuration:

## shopify.app.toml

```toml
[network_access]
allowed_navigation_hosts = [
  "app.example.com",
  "help.app.example.com",
]
allowed_sources = [
  "https://api.app.example.com",
  "https://cdn.app.example.com",
]
```

***

## Verify

Run [`shopify app deploy`](https://shopify.dev/docs/api/shopify-cli/app/app-deploy). Shopify checks both lists when it creates the app version, and rejects the deploy if an entry doesn't follow the rules in the [`network_access` reference](https://shopify.dev/docs/apps/build/cli-for-apps/app-configuration#network_access).

***
