Skip to main content
The baseURL option allows you to set a base path for all requests, making it easy to work with APIs without repeating the full URL.

Basic Usage

import { ofetch } from 'ofetch'

const data = await ofetch('/users', {
  baseURL: 'https://api.example.com'
})
// Request: https://api.example.com/users

Smart Slash Handling

ofetch intelligently handles trailing and leading slashes, so you don’t have to worry about double slashes or missing separators:
// All of these work correctly
await ofetch('/users', { baseURL: 'https://api.example.com' })
await ofetch('/users', { baseURL: 'https://api.example.com/' })
await ofetch('users', { baseURL: 'https://api.example.com' })
await ofetch('users', { baseURL: 'https://api.example.com/' })

// All result in: https://api.example.com/users

Creating a Configured Instance

The most common pattern is to create a configured instance with $fetch.create():
import { ofetch } from 'ofetch'

const api = ofetch.create({
  baseURL: 'https://api.example.com',
  headers: {
    'Authorization': 'Bearer token123'
  }
})

// Now all requests use the baseURL
await api('/users')          // https://api.example.com/users
await api('/posts')          // https://api.example.com/posts
await api('/comments/123')   // https://api.example.com/comments/123

Nested Paths

baseURL works with nested API paths:
const api = ofetch.create({
  baseURL: 'https://api.example.com/v2'
})

await api('/users/123/posts')
// Request: https://api.example.com/v2/users/123/posts

With Query Parameters

baseURL combines seamlessly with query parameters:
await ofetch('/search', {
  baseURL: 'https://api.example.com',
  query: { q: 'ofetch', page: 1 }
})
// Request: https://api.example.com/search?q=ofetch&page=1

Overriding baseURL

You can override the baseURL for specific requests by providing a full URL:
const api = ofetch.create({
  baseURL: 'https://api.example.com'
})

// This uses the baseURL
await api('/users')
// Request: https://api.example.com/users

// This overrides it (full URL provided)
await api('https://other-api.com/data')
// Request: https://other-api.com/data

Environment-Based Configuration

Common pattern for different environments:
const api = ofetch.create({
  baseURL: process.env.API_BASE_URL || 'http://localhost:3000'
})

// Development: http://localhost:3000/users
// Production: https://api.example.com/users

Multiple API Clients

Create different clients for different services:
const usersAPI = ofetch.create({
  baseURL: 'https://users.example.com'
})

const paymentsAPI = ofetch.create({
  baseURL: 'https://payments.example.com'
})

await usersAPI('/profile')      // https://users.example.com/profile
await paymentsAPI('/checkout')  // https://payments.example.com/checkout

Type Definition

From src/types.ts:25:
baseURL?: string

Implementation Details

The baseURL logic is handled at src/fetch.ts:114-117 using the withBase function from src/utils.url.ts:40-51:
  • If the request already starts with the baseURL, it’s returned as-is
  • Trailing slashes on baseURL are removed
  • The request path is joined with proper slash handling
This prevents issues like:
  • Double slashes: https://api.example.com//users
  • Missing slashes: https://api.example.comusers

Build docs developers (and LLMs) love