The hc() function creates a type-safe HTTP client that automatically infers types from your Hono server routes. It uses Proxy objects to provide a chainable API that mirrors your server’s route structure.
Standard RequestInit options. Caution: This takes highest priority and can overwrite settings that Hono sets automatically (like body, method, headers)
Custom function to serialize query parameters into URLSearchParams. By default, arrays are serialized as multiple parameters with the same key (e.g., key=a&key=b). You can provide a custom function to change this behavior.
type BuildSearchParamsFn = (query: Record<string, string | string[]>) => URLSearchParams
Example: Using bracket notation for arrays
import qs from 'qs'const client = hc('http://localhost:3000', { buildSearchParams: (query) => { return new URLSearchParams(qs.stringify(query)) }})
import { hc } from 'hono/client'import type { AppType } from './server'const client = hc<AppType>('http://localhost:3000')// Make a GET requestconst response = await client.api.posts.$get()const data = await response.json()
import { hc } from 'hono/client'import type { AppType } from './server'const client = hc<AppType>('http://localhost:3000', { fetch: customFetch // Useful for testing with MSW or node-fetch})
// GET with query parametersconst res = await client.api.search.$get({ query: { q: 'hono', limit: '10' }})// POST with JSON bodyconst res = await client.api.posts.$post({ json: { title: 'Hello Hono', content: 'This is a post' }})// PUT with path parametersconst res = await client.api.posts[':id'].$put({ param: { id: '123' }, json: { title: 'Updated Title' }})// DELETE with path parametersconst res = await client.api.posts[':id'].$delete({ param: { id: '123' }})// POST with form dataconst res = await client.api.upload.$post({ form: { file: fileBlob, name: 'document.pdf' }})
All HTTP methods return a Promise<ClientResponse> which extends the standard Response interface with type-safe methods:
const response = await client.api.posts.$get()// Type-safe JSON parsingconst data = await response.json() // Type is inferred from server// Text responseconst text = await response.text()// Other Response methodsconst blob = await response.blob()const buffer = await response.arrayBuffer()const bytes = await response.bytes()const formData = await response.formData()// Response propertiesconsole.log(response.status) // HTTP status codeconsole.log(response.ok) // true if status is 2xxconsole.log(response.headers) // Response headersconsole.log(response.statusText) // Status text