Documentation Index Fetch the complete documentation index at: https://mintlify.com/unjs/ofetch/llms.txt
Use this file to discover all available pages before exploring further.
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
With baseURL
Before (native fetch)
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
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:
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