Skip to content

createFetch ​

Shared HTTP API — always available with any Framework filter (tagged core).

ts
import { createFetch } from 'tanstack-fetch'

const api = createFetch(options?)

For SSE, import from tanstack-fetch/sse instead. For WebSocket, WebTransport and NDJSON streams (plus SSE), import from tanstack-fetch/live — see WebSocket, WebTransport & streams.

The core tanstack-fetch entry takes CoreFetchOptions (baseUrl, headers, source, incoming, timeoutMs, interceptors, fetch, credentials, maxRetries) and returns a CoreFetchClient (no upload(), progress events ignored). Rows marked full only are accepted by tanstack-fetch/sse, /live, /trpc and framework providers; on core use the tanstack-fetch/plugins factories:

ts
import { createFetch } from 'tanstack-fetch'
import {
  createAuthInterceptor,
  createStatusInterceptor,
  createTraceInterceptor,
} from 'tanstack-fetch/plugins'

const api = createFetch({
  baseUrl: 'https://api.example.com',
  interceptors: [
    createAuthInterceptor({ getToken: () => localStorage.getItem('access_token') }), // getToken / auth
    createStatusInterceptor({ 401: () => logout(), '5xx': ({ status }) => console.error(status) }), // onX / onStatus
    createTraceInterceptor(), // plugins: ['trace']
  ],
})

CreateFetchOptions ​

OptionTypeNotes
baseUrlstringAbsolute URL required for SSR / Edge
headersHeadersInit | getterMerged into every request
getToken() => tokenSets Bearer auth — full only
auth{ getToken, header?, scheme? }Advanced auth — full only
onBadRequeststatus handlerHTTP 400 — full only
onUnauthorizedstatus handlerHTTP 401 — full only
onForbiddenstatus handlerHTTP 403 — full only
onNotFoundstatus handlerHTTP 404 — full only
onMethodNotAllowedstatus handlerHTTP 405 — full only
onRequestTimeoutstatus handlerHTTP 408 — full only
onConflictstatus handlerHTTP 409 — full only
onGonestatus handlerHTTP 410 — full only
onPayloadTooLargestatus handlerHTTP 413 — full only
onUnsupportedMediaTypestatus handlerHTTP 415 — full only
onUnprocessableEntitystatus handlerHTTP 422 — full only
onTooManyRequestsstatus handlerHTTP 429 — full only
onUnavailableForLegalReasonsstatus handlerHTTP 451 — full only
onClientErrorstatus handlerAny other 4xx — full only
onServerErrorstatus handlerHTTP 5xx — full only
onStatusstatus mapExact / 4xx / 5xx / default — full only
pluginsPluginName[]Built-in interceptors — full only
interceptorsHttpInterceptor[]Custom
timeoutMsnumberPer-client timeout (default 30 000) → TimeoutError
maxRetriesnumberRetry budget
fetchtypeof fetchCustom fetch / tests
credentialsRequestCredentialse.g. include
createWebSocketCreateWebSocketapi.ws socket factory (e.g. ws on Node < 22) — /live only
createWebTransportCreateWebTransportapi.transport factory (polyfills) — /live only
source'browser' | 'ssr' | …Runtime hint
incomingheaders | getterSSR forward input

Also exported: parseRetryAfter(headers) for 429 Retry-After → ms.

Path-typed params ​

Path placeholders make params required and typed (:id or {id}):

ts
import { createFetch, pathParams } from 'tanstack-fetch'
import type { NoParams } from 'tanstack-fetch'

type User = { id: string; name: string }

const api = createFetch({ baseUrl: 'https://api.example.com' })

// params required — keys inferred from the path
await api.get('/users/:id', { params: { id: '1' } })

// response + params map — path must contain matching :id / {id}
await api.get<User, { id: string | number }>('/users/:id', { params: { id: '1' } })

// post / put / patch — optional body type (use `NoParams` when there are no path params)
await api.post<User, NoParams, { name: string }>('/users', { body: { name: 'Ada' } })

await api.get('/users/{id}/posts/{postId}', {
  params: pathParams('/users/{id}/posts/{postId}', { id: 1, postId: 2 }),
})

// no placeholders → params not accepted
await api.get('/users')

Only the pathname is scanned for placeholders, so absolute URLs with a port and colons in the query are safe:

ts
await api.get('http://localhost:8080/users/:id?at=10:30', { params: { id: '1' } })
// → http://localhost:8080/users/1?at=10:30

Helpers / types: pathParams(), PathParamsOf, ExtractPathParamKeys, NoParams.

Deprecated alias: createClient → createFetch.

With React ​

Inject the client via tanstack-fetch/react (FetchProvider / useFetch). API reference: React.

With Vue / Nuxt ​

Inject via tanstack-fetch/vue (createFetchPlugin / useFetch). API: Vue.

With Solid ​

Inject via tanstack-fetch/solid.

With Angular ​

Inject via tanstack-fetch/angular (provideFetchClient / injectFetch).

With Svelte ​

Inject via tanstack-fetch/svelte (setFetchClient / useFetch).

MIT Licensed · Created by Mohammad Garmabi · Not an official TanStack package