---
navigation.title: 'Custom useFetch'
title: Custom useFetch in Nuxt
description: How to create a custom fetcher for calling your external API in Nuxt.
---

When working with Nuxt, you might be making the frontend and fetching an external API, and you might want to set some default options for fetching from your API.

The [`$fetch`](/docs/4.x/api/utils/dollarfetch) utility function (used by the [`useFetch`](/docs/4.x/api/composables/use-fetch) composable) is intentionally not globally configurable. This is important so that fetching behavior throughout your application remains consistent, and other integrations (like modules) can rely on the behavior of core utilities like `$fetch`.

However, Nuxt provides a way to create a custom fetcher for your API (or multiple fetchers if you have multiple APIs to call).

## Recipe: API Client with Auth

Let's say you have an external API at `https://api.nuxt.com` that requires JWT authentication via [nuxt-auth-utils](https://github.com/atinux/nuxt-auth-utils), and you want to redirect to `/login` on `401` responses.

```ts [app/composables/useAPI.ts]
export const useAPI = createUseFetch({
  baseURL: 'https://api.nuxt.com',
  onRequest ({ options }) {
    const { session } = useUserSession()
    if (session.value?.token) {
      options.headers.set('Authorization', `Bearer ${session.value.token}`)
    }
  },
  async onResponseError ({ response }) {
    if (response.status === 401) {
      await navigateTo('/login')
    }
  },
})
```

Now every call to `useAPI` automatically includes the auth header and handles 401 redirects:

```vue [app/pages/dashboard.vue]
<script setup lang="ts">
const { data: profile } = await useAPI('/me')
const { data: orders } = await useAPI('/orders')
</script>
```

:read-more{to="/docs/4.x/api/composables/create-use-fetch"}

## Recipe: Custom `$fetch` Instance

If you need lower-level control, you can create a custom `$fetch` instance with a [Nuxt plugin](/docs/4.x/directory-structure/app/plugins) and either use it with `useAsyncData` directly or pass it to `createUseFetch`.

::note
`$fetch` is a configured instance of [ofetch](https://github.com/unjs/ofetch) which supports adding the base URL of your Nuxt server as well as direct function calls during SSR (avoiding HTTP roundtrips).
::

```ts [app/plugins/api.ts]
export default defineNuxtPlugin((nuxtApp) => {
  const { session } = useUserSession()

  const api = $fetch.create({
    baseURL: 'https://api.nuxt.com',
    onRequest ({ request, options, error }) {
      if (session.value?.token) {
        options.headers.set('Authorization', `Bearer ${session.value?.token}`)
      }
    },
    async onResponseError ({ response }) {
      if (response.status === 401) {
        await nuxtApp.runWithContext(() => navigateTo('/login'))
      }
    },
  })

  return {
    provide: {
      api,
    },
  }
})
```

You can then use the custom `$fetch` instance directly:

```vue [app/app.vue]
<script setup>
const { $api } = useNuxtApp()
const { data: modules } = await useAsyncData('modules', () => $api('/modules'))
</script>
```

::callout
Wrapping with [`useAsyncData`](/docs/4.x/api/composables/use-async-data) **avoids double data fetching when doing server-side rendering** (server & client on hydration).
::

:link-example{to="/docs/4.x/examples/advanced/use-custom-fetch-composable"}

:video-accordion{title="Watch a video about custom $fetch and Repository Pattern in Nuxt" videoId="jXH8Tr-exhI"}
