> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/honojs/hono/llms.txt
> Use this file to discover all available pages before exploring further.

# Context

> Context object passed to route handlers and middleware

# Context

The `Context` object is passed to every route handler and middleware function. It provides access to the request, response helpers, environment bindings, and context variables.

## Constructor

You typically don't create Context instances directly. Hono creates them for each request.

```typescript theme={null}
const c = new Context(request, options?)
```

## Request Properties

### req

The HonoRequest instance for accessing request data.

```typescript theme={null}
c.req: HonoRequest<P, I['out']>
```

```typescript theme={null}
app.get('/users/:id', (c) => {
  const id = c.req.param('id')
  const query = c.req.query('search')
  return c.json({ id, query })
})
```

See the [HonoRequest API reference](/api/request) for available methods.

### env

Environment bindings (e.g., Cloudflare Workers KV, D1, etc.).

```typescript theme={null}
c.env: E['Bindings']
```

```typescript theme={null}
app.get('/todos', async (c) => {
  // Access Cloudflare D1 database
  const todos = await c.env.DB.prepare('SELECT * FROM todos').all()
  return c.json(todos)
})
```

### event

The FetchEvent associated with the current request (Cloudflare Workers).

```typescript theme={null}
c.event: FetchEventLike
```

<Note>
  Throws an error if the context does not have a FetchEvent.
</Note>

```typescript theme={null}
app.get('/data', async (c) => {
  // Use waitUntil for async operations that shouldn't block response
  c.event.waitUntil(
    fetch('https://analytics.example.com/track')
  )
  return c.text('OK')
})
```

### executionCtx

The ExecutionContext for the current request.

```typescript theme={null}
c.executionCtx: ExecutionContext
```

<Note>
  Throws an error if the context does not have an ExecutionContext.
</Note>

```typescript theme={null}
app.get('/data', async (c) => {
  c.executionCtx.waitUntil(analyticsTask())
  return c.text('Processing')
})
```

### error

Error object if a handler threw an error (available in error handlers).

```typescript theme={null}
c.error: Error | undefined
```

```typescript theme={null}
app.use('*', async (c, next) => {
  await next()
  if (c.error) {
    console.error('Request error:', c.error)
  }
})
```

### finalized

Boolean indicating whether the response has been finalized.

```typescript theme={null}
c.finalized: boolean
```

### res

The Response object for the current request.

```typescript theme={null}
c.res: Response
```

```typescript theme={null}
app.use('*', async (c, next) => {
  await next()
  console.log('Status:', c.res.status)
})
```

## Response Methods

### text

Respond with plain text.

```typescript theme={null}
c.text(text, status?, headers?)
c.text(text, init?)
```

<ParamField path="text" type="string" required>
  Text content to send
</ParamField>

<ParamField path="status" type="StatusCode" optional>
  HTTP status code (default: 200)
</ParamField>

<ParamField path="headers" type="HeaderRecord" optional>
  Additional headers to set
</ParamField>

<ResponseField name="return" type="Response">
  Response with Content-Type: text/plain
</ResponseField>

```typescript theme={null}
app.get('/hello', (c) => {
  return c.text('Hello, World!')
})

app.get('/error', (c) => {
  return c.text('Not Found', 404)
})
```

### json

Respond with JSON.

```typescript theme={null}
c.json(object, status?, headers?)
c.json(object, init?)
```

<ParamField path="object" type="JSONValue | {}" required>
  Object to serialize as JSON
</ParamField>

<ParamField path="status" type="StatusCode" optional>
  HTTP status code (default: 200)
</ParamField>

<ParamField path="headers" type="HeaderRecord" optional>
  Additional headers to set
</ParamField>

<ResponseField name="return" type="Response">
  Response with Content-Type: application/json
</ResponseField>

```typescript theme={null}
app.get('/api/user', (c) => {
  return c.json({ name: 'John', age: 30 })
})

app.post('/api/user', async (c) => {
  const body = await c.req.json()
  return c.json({ created: true }, 201)
})
```

### html

Respond with HTML.

```typescript theme={null}
c.html(html, status?, headers?)
c.html(html, init?)
```

<ParamField path="html" type="string | Promise<string>" required>
  HTML content to send
</ParamField>

<ParamField path="status" type="StatusCode" optional>
  HTTP status code (default: 200)
</ParamField>

<ParamField path="headers" type="HeaderRecord" optional>
  Additional headers to set
</ParamField>

<ResponseField name="return" type="Response | Promise<Response>">
  Response with Content-Type: text/html
</ResponseField>

```typescript theme={null}
app.get('/', (c) => {
  return c.html('<h1>Hello, World!</h1>')
})

app.get('/page', (c) => {
  return c.html(
    <html>
      <body>
        <h1>Welcome</h1>
      </body>
    </html>
  )
})
```

### body

Respond with a raw body.

```typescript theme={null}
c.body(data, status?, headers?)
c.body(data, init?)
```

<ParamField path="data" type="Data | null" required>
  Body data (string, ArrayBuffer, ReadableStream, or Uint8Array)
</ParamField>

<ParamField path="status" type="StatusCode" optional>
  HTTP status code
</ParamField>

<ParamField path="headers" type="HeaderRecord" optional>
  Headers to set
</ParamField>

<ResponseField name="return" type="Response">
  Response with the provided body
</ResponseField>

```typescript theme={null}
app.get('/binary', (c) => {
  const buffer = new Uint8Array([1, 2, 3, 4])
  return c.body(buffer)
})
```

### redirect

Redirect to a different URL.

```typescript theme={null}
c.redirect(location, status?)
```

<ParamField path="location" type="string | URL" required>
  URL to redirect to
</ParamField>

<ParamField path="status" type="RedirectStatusCode" optional>
  HTTP redirect status code (default: 302)
</ParamField>

<ResponseField name="return" type="Response">
  Redirect response with Location header
</ResponseField>

```typescript theme={null}
app.get('/old-path', (c) => {
  return c.redirect('/new-path')
})

app.get('/permanent', (c) => {
  return c.redirect('/new-url', 301)
})
```

### notFound

Return a 404 Not Found response.

```typescript theme={null}
c.notFound()
```

<ResponseField name="return" type="Response">
  404 Not Found response
</ResponseField>

```typescript theme={null}
app.get('/users/:id', async (c) => {
  const user = await findUser(c.req.param('id'))
  if (!user) {
    return c.notFound()
  }
  return c.json(user)
})
```

### newResponse

Create a new Response with merged headers.

```typescript theme={null}
c.newResponse(data, status?, headers?)
c.newResponse(data, init?)
```

<ParamField path="data" type="Data | null" required>
  Response body
</ParamField>

<ParamField path="status" type="StatusCode" optional>
  HTTP status code
</ParamField>

<ParamField path="headers" type="HeaderRecord" optional>
  Headers to set
</ParamField>

<ResponseField name="return" type="Response">
  New Response with headers merged from c.header() calls
</ResponseField>

```typescript theme={null}
app.get('/data', (c) => {
  c.header('X-Custom', 'value')
  return c.newResponse('Hello', 200)
})
```

## Header Methods

### header

Set a response header.

```typescript theme={null}
c.header(name, value?, options?)
```

<ParamField path="name" type="string" required>
  Header name
</ParamField>

<ParamField path="value" type="string" optional>
  Header value. If undefined, the header is deleted.
</ParamField>

<ParamField path="options" type="SetHeadersOptions" optional>
  Options object with `append` boolean
</ParamField>

```typescript theme={null}
app.get('/data', (c) => {
  c.header('X-Custom', 'value')
  c.header('Content-Type', 'application/json')
  return c.body(JSON.stringify({ data: 'value' }))
})

// Append header
c.header('Set-Cookie', 'token=abc', { append: true })
c.header('Set-Cookie', 'user=john', { append: true })
```

### status

Set the response status code.

```typescript theme={null}
c.status(status)
```

<ParamField path="status" type="StatusCode" required>
  HTTP status code to set
</ParamField>

```typescript theme={null}
app.get('/data', (c) => {
  c.status(201)
  return c.json({ created: true })
})
```

<Note>
  It's usually cleaner to pass the status directly to response methods like `c.json(data, 201)` instead of calling `c.status()` separately.
</Note>

## Context Variables

Context variables allow you to pass data between middleware and handlers.

### set

Set a context variable.

```typescript theme={null}
c.set(key, value)
```

<ParamField path="key" type="string" required>
  Variable name
</ParamField>

<ParamField path="value" type="any" required>
  Value to store
</ParamField>

```typescript theme={null}
app.use('*', async (c, next) => {
  c.set('requestTime', Date.now())
  c.set('user', { id: 1, name: 'John' })
  await next()
})
```

### get

Get a context variable.

```typescript theme={null}
c.get(key)
```

<ParamField path="key" type="string" required>
  Variable name
</ParamField>

<ResponseField name="return" type="any">
  The stored value, or undefined if not set
</ResponseField>

```typescript theme={null}
app.get('/', (c) => {
  const user = c.get('user')
  const time = c.get('requestTime')
  return c.json({ user, time })
})
```

### var

Read-only object containing all context variables.

```typescript theme={null}
c.var: Readonly<ContextVariableMap & E['Variables']>
```

```typescript theme={null}
app.get('/', (c) => {
  const { user, requestTime } = c.var
  return c.json({ user, requestTime })
})
```

<Note>
  `c.var` provides type-safe access to variables when using TypeScript with proper type definitions.
</Note>

## Rendering Methods

### render

Render content using the configured renderer.

```typescript theme={null}
c.render(...args)
```

<ResponseField name="return" type="Response | Promise<Response>">
  Rendered response
</ResponseField>

```typescript theme={null}
app.get('/', (c) => {
  return c.render('Hello!')
})
```

### setRenderer

Set a custom renderer for the application.

```typescript theme={null}
c.setRenderer(renderer)
```

<ParamField path="renderer" type="Renderer" required>
  Function that renders content to a Response
</ParamField>

```typescript theme={null}
app.use('*', async (c, next) => {
  c.setRenderer((content) => {
    return c.html(
      <html>
        <body>
          <div>{content}</div>
        </body>
      </html>
    )
  })
  await next()
})

app.get('/', (c) => c.render('Hello!'))
// Renders: <html><body><div>Hello!</div></body></html>
```

### setLayout

Set a layout component.

```typescript theme={null}
c.setLayout(layout)
```

<ParamField path="layout" type="Layout" required>
  Layout component function
</ParamField>

<ResponseField name="return" type="Layout">
  The layout function
</ResponseField>

### getLayout

Get the current layout.

```typescript theme={null}
c.getLayout()
```

<ResponseField name="return" type="Layout | undefined">
  The current layout function, or undefined
</ResponseField>

## Type Parameters

The Context class accepts generic type parameters for type safety:

<ParamField path="E" type="Env" default="any">
  Environment type defining bindings and variables
</ParamField>

<ParamField path="P" type="string" default="any">
  Path parameter type for type-safe param access
</ParamField>

<ParamField path="I" type="Input" default="{}">
  Input type for validated data
</ParamField>

```typescript theme={null}
type Env = {
  Bindings: {
    DB: D1Database
  }
  Variables: {
    user: User
  }
}

app.get('/users/:id', (c: Context<Env, '/users/:id'>) => {
  const id = c.req.param('id') // Type-safe
  const db = c.env.DB // Type-safe
  const user = c.var.user // Type-safe
  return c.json({ id })
})
```
