Skip to main content

HonoRequest

The HonoRequest class wraps the standard Web API Request object and provides convenient methods for accessing request data. It’s available through c.req in handlers and middleware.

Constructor

You typically don’t create HonoRequest instances directly. They’re created by Hono for each request.
const req = new HonoRequest(request, path?, matchResult?)

Properties

raw

The underlying Web API Request object.
req.raw: Request
app.post('/', async (c) => {
  // Access raw request
  const contentType = c.req.raw.headers.get('content-type')
  return c.text(`Content-Type: ${contentType}`)
})

path

The pathname of the request URL.
req.path: string
app.get('/about/me', (c) => {
  const pathname = c.req.path // '/about/me'
  return c.text(`Current path: ${pathname}`)
})

url

The full URL of the request.
req.url: string
app.get('/about/me', (c) => {
  const url = c.req.url // 'http://localhost:8787/about/me'
  return c.text(`URL: ${url}`)
})

method

The HTTP method of the request.
req.method: string
app.all('*', (c) => {
  const method = c.req.method // 'GET', 'POST', etc.
  return c.text(`Method: ${method}`)
})

Path Parameters

param

Get path parameters from the route.
req.param(key?)
key
string
Parameter name. If omitted, returns all parameters as an object.
return
string | Record<string, string> | undefined
The parameter value(s)
// Single parameter
app.get('/users/:id', (c) => {
  const id = c.req.param('id')
  return c.json({ id })
})

// All parameters
app.get('/posts/:postId/comments/:commentId', (c) => {
  const { postId, commentId } = c.req.param()
  return c.json({ postId, commentId })
})

// Optional parameters
app.get('/users/:id?', (c) => {
  const id = c.req.param('id') // string | undefined
  return c.json({ id })
})

Query Parameters

query

Get a query string parameter.
req.query(key?)
key
string
Query parameter name. If omitted, returns all parameters as an object.
return
string | Record<string, string> | undefined
The query parameter value(s)
// Single query parameter
// GET /search?q=hono
app.get('/search', (c) => {
  const query = c.req.query('q') // 'hono'
  return c.json({ query })
})

// All query parameters
// GET /search?q=hono&limit=10&offset=0
app.get('/search', (c) => {
  const { q, limit, offset } = c.req.query()
  return c.json({ q, limit, offset })
})

queries

Get multiple values for a query parameter (e.g., array values).
req.queries(key?)
key
string
Query parameter name. If omitted, returns all parameters as arrays.
return
string[] | Record<string, string[]> | undefined
The query parameter value(s) as arrays
// Multiple values for same parameter
// GET /search?tags=typescript&tags=javascript&tags=hono
app.get('/search', (c) => {
  const tags = c.req.queries('tags') // ['typescript', 'javascript', 'hono']
  return c.json({ tags })
})

// All parameters as arrays
app.get('/search', (c) => {
  const params = c.req.queries()
  // { tags: ['typescript', 'javascript'], q: ['hono'] }
  return c.json(params)
})

Headers

Get request header value(s).
req.header(name?)
name
string
Header name. If omitted, returns all headers as an object.
return
string | Record<string, string> | undefined
The header value(s)
// Single header
app.get('/', (c) => {
  const userAgent = c.req.header('User-Agent')
  return c.text(`User-Agent: ${userAgent}`)
})

// All headers
app.get('/headers', (c) => {
  const headers = c.req.header()
  return c.json(headers)
})

Request Body

json

Parse the request body as JSON.
req.json<T = any>()
return
Promise<T>
Parsed JSON object
app.post('/api/users', async (c) => {
  const body = await c.req.json()
  return c.json({ received: body })
})

// With type annotation
type CreateUser = {
  name: string
  email: string
}

app.post('/api/users', async (c) => {
  const body = await c.req.json<CreateUser>()
  // body.name and body.email are typed
  return c.json({ created: body })
})

text

Parse the request body as plain text.
req.text()
return
Promise<string>
Request body as a string
app.post('/webhook', async (c) => {
  const body = await c.req.text()
  console.log('Received:', body)
  return c.text('OK')
})

arrayBuffer

Parse the request body as an ArrayBuffer.
req.arrayBuffer()
return
Promise<ArrayBuffer>
Request body as an ArrayBuffer
app.post('/upload', async (c) => {
  const buffer = await c.req.arrayBuffer()
  // Process binary data
  return c.text(`Received ${buffer.byteLength} bytes`)
})

blob

Parse the request body as a Blob.
req.blob()
return
Promise<Blob>
Request body as a Blob
app.post('/upload', async (c) => {
  const blob = await c.req.blob()
  return c.text(`Received blob of type: ${blob.type}`)
})

formData

Parse the request body as FormData.
req.formData()
return
Promise<FormData>
Request body as FormData
app.post('/submit', async (c) => {
  const formData = await c.req.formData()
  const name = formData.get('name')
  const file = formData.get('file') as File
  return c.json({ name, fileName: file?.name })
})

parseBody

Parse multipart/form-data or application/x-www-form-urlencoded bodies.
req.parseBody<T = BodyData>(options?)
options
ParseBodyOptions
Parsing options
return
Promise<T>
Parsed body data as an object
app.post('/form', async (c) => {
  const body = await c.req.parseBody()
  // { name: 'John', email: 'john@example.com' }
  return c.json(body)
})

// Handle multiple values
app.post('/tags', async (c) => {
  const body = await c.req.parseBody({ all: true })
  // { tag: ['typescript', 'javascript', 'hono'] }
  return c.json(body)
})

// Handle file uploads
app.post('/upload', async (c) => {
  const body = await c.req.parseBody()
  const file = body.file as File
  return c.text(`Uploaded: ${file.name}`)
})

Validated Data

valid

Get validated data from validators.
req.valid(target)
target
keyof ValidationTargets
required
Validation target: ‘json’, ‘form’, ‘query’, ‘param’, ‘header’, or ‘cookie’
return
T
The validated data
import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'

const schema = z.object({
  name: z.string(),
  age: z.number()
})

app.post(
  '/users',
  zValidator('json', schema),
  async (c) => {
    const validated = c.req.valid('json')
    // validated.name and validated.age are typed and validated
    return c.json(validated)
  }
)

addValidatedData

Add validated data to the request (used internally by validators).
req.addValidatedData(target, data)
target
keyof ValidationTargets
required
Validation target
data
object
required
Validated data to store

Deprecated Methods

matchedRoutes

Deprecated. Use the matchedRoutes helper from hono/route instead.
Get matched routes for the current request.
req.matchedRoutes: RouterRoute[]

routePath

Deprecated. Use the routePath helper from hono/route instead.
Get the path of the matched route.
req.routePath: string

Utility Functions

cloneRawRequest

Clone a HonoRequest’s underlying raw Request object, handling both consumed and unconsumed bodies.
cloneRawRequest(req)
req
HonoRequest
required
The HonoRequest to clone
return
Promise<Request>
A new Request object with the same properties
import { cloneRawRequest } from 'hono/request'

app.post('/forward', async (c) => {
  const body = await c.req.json()
  // Body has been consumed, but we can still clone
  const clonedReq = await cloneRawRequest(c.req)
  // Forward to another service
  return fetch('http://backend.example.com', clonedReq)
})
This is particularly useful when you need to:
  • Process the same request body multiple times
  • Pass requests to external services after validation
  • Forward requests after consuming the body

Type Parameters

The HonoRequest class accepts generic type parameters:
P
string
default:"'/'"
Path parameter type for type-safe param access
I
Input['out']
default:"{}"
Input type for validated data
type Params = '/users/:id'

app.get('/users/:id', (c) => {
  const req: HonoRequest<Params> = c.req
  const id = req.param('id') // Type-safe
  return c.json({ id })
})

Build docs developers (and LLMs) love