Last Updated: 3/11/2026
Context & Request
The Context object (c) is created for each request and provides methods to handle requests and build responses.
Request Object (c.req)
c.req is a HonoRequest instance that provides methods to access request data.
Headers
app.get('/hello', (c) => {
const userAgent = c.req.header('User-Agent')
return c.text(`Your UA: ${userAgent}`)
})Path Parameters
app.get('/user/:name', (c) => {
const name = c.req.param('name')
return c.text(`Hello, ${name}!`)
})
// Get all parameters
app.get('/posts/:id/comment/:comment_id', (c) => {
const { id, comment_id } = c.req.param()
return c.json({ id, comment_id })
})Query Parameters
app.get('/search', (c) => {
const query = c.req.query('q')
const page = c.req.query('page') || '1'
return c.json({ query, page })
})Request Body
// JSON body
app.post('/api/data', async (c) => {
const body = await c.req.json()
return c.json({ received: body })
})
// Form data
app.post('/submit', async (c) => {
const body = await c.req.parseBody()
return c.json({ received: body })
})
// Text body
app.post('/text', async (c) => {
const text = await c.req.text()
return c.text(`You sent: ${text}`)
})Response Methods
Text Response
Return plain text with Content-Type: text/plain:
app.get('/say', (c) => {
return c.text('Hello!')
})JSON Response
Return JSON with Content-Type: application/json:
app.get('/api', (c) => {
return c.json({ message: 'Hello!' })
})HTML Response
Return HTML with Content-Type: text/html:
app.get('/', (c) => {
return c.html('<h1>Hello! Hono!</h1>')
})Raw Body
Return a raw response body:
app.get('/welcome', (c) => {
return c.body('Thank you for coming')
})
// With status and headers
app.get('/welcome', (c) => {
return c.body('Thank you', 201, {
'X-Message': 'Hello!',
'Content-Type': 'text/plain',
})
})Setting Status and Headers
Status Code
app.post('/posts', (c) => {
c.status(201)
return c.text('Your post is created!')
})Headers
app.get('/', (c) => {
c.header('X-Message', 'My custom message')
c.header('X-Response-Time', '42ms')
return c.text('Hello!')
})Redirects
Redirect to another URL (default status: 302):
app.get('/redirect', (c) => {
return c.redirect('/')
})
app.get('/redirect-permanently', (c) => {
return c.redirect('/', 301)
})Not Found
Return a 404 response:
app.get('/notfound', (c) => {
return c.notFound()
})Variables (c.set / c.get)
Pass values between middleware and handlers:
type Variables = {
message: string
}
const app = new Hono<{ Variables: Variables }>()
app.use(async (c, next) => {
c.set('message', 'Hono is cool!!')
await next()
})
app.get('/', (c) => {
const message = c.get('message')
return c.text(`The message is "${message}"`)
})Access variables with c.var:
app.get('/', (c) => {
const message = c.var.message
return c.text(message)
})Rendering (c.setRenderer / c.render)
Set a layout in middleware:
app.use(async (c, next) => {
c.setRenderer((content) => {
return c.html(
<html>
<body>
<p>{content}</p>
</body>
</html>
)
})
await next()
})Render content using the layout:
app.get('/', (c) => {
return c.render('Hello!')
})Platform-Specific Features
Cloudflare Workers
Access bindings via c.env:
type Bindings = {
MY_KV: KVNamespace
USERNAME: string
}
const app = new Hono<{ Bindings: Bindings }>()
app.get('/', async (c) => {
const value = await c.env.MY_KV.get('my-key')
return c.json({ value })
})Access ExecutionContext:
app.get('/foo', async (c) => {
c.executionCtx.waitUntil(
c.env.MY_KV.put('key', 'value')
)
return c.text('Done')
})Node.js
Access raw Node.js APIs:
import { serve, type HttpBindings } from '@hono/node-server'
type Bindings = HttpBindings
const app = new Hono<{ Bindings: Bindings }>()
app.get('/', (c) => {
return c.json({
remoteAddress: c.env.incoming.socket.remoteAddress,
})
})Error Handling
Access errors in middleware:
app.use(async (c, next) => {
await next()
if (c.error) {
console.error('Error occurred:', c.error)
}
})Next Steps
Learn about Middleware to add functionality across your routes.