Official documentation of the itty ecosystem.

GitHub edit this page

NPM GitHub


Creates a preflight middleware and corsify Response-handler. Used together, this handles both OPTIONS requests as well as appends the appropriate CORS headers to created Responses.


import { Router, createCors, error, json } from 'itty-router'

const { preflight, corsify } = createCors({
  origins: ['*'],
  methods: ['GET', 'POST', 'PATCH', 'DELETE'],

const router = Router()

  // embed preflight upstream to handle all OPTIONS requests
  .all('*', preflight)

  .get('/foo', () => 'bar')

export default {
  fetch: (...args) => router

                        // embed corsify downstream to attach CORS headers


Creates a response helper from a MIME-type (string), and optionally, a body-transform (function).

createResponse(mimeType: string, transform?: Function): ResponseHelper

For example, here’s how we created the json helper:

import { createResponse } from 'itty-router'

export const json = createResponse('application/json', JSON.stringify)

json({ foo: 'bar' }) // creates JSON-formatted Response


Returns an error Response

error(code: number, body?: string | object): Response

error(error: Error | StatusError): Response

html new in v4.x

Returns an HTML Response

html(string, options?: ResponseInit): Response

jpeg new in v4.x

Returns a JPEG Response

jpeg(data, options?: ResponseInit): Response


Returns a JSON Response

json(data, options?: ResponseInit): Response

png new in v4.x

Returns a PNG Response

png(data, options?: ResponseInit): Response


Constructor function, returning a router Proxy (object).

Router(options?: RouterOptions): RouterType


Name Type(s) Description
base string prefixes all routes with this string
routes RouteEntry[] array of manual routes for preloading

The router itself has essentially two properties:

  • The “handle”

    router.handle(request: IRequest, ...args): Promise

    The handle function takes a request-like argument, returning a Promise. This will resolve to anything returned from a matching route, or nothing at all (if no route returns).

  • The route registers

    router[method: string](route: string, ...handlers): Router

    Any other property accessed off the router object maps to the corresponding uppercase HTTP method (even non-standard ones), returning a function that takes a path (string) and any number of handlers/middleware, and returns the router again (for optional declaration chaining).

    The one notable exception to this is the .all() channel, which matches to any HTTP method (similar to .use() in many other routers).

    import { Router, error, withParams } from 'itty-router'
    import { todos } from './fake-todo-service'
    // define a router
    const router = Router()
      // this route will match *any* HTTP method, e.g. POST, PUT, GET
        ({ method }) => `Accessed via the ${method} HTTP method`
      // GET todos list or single todo
      .get('/todos/:id?', withParams, 
        ({ id }) => id
                    ? (todos.getTodo(id) || error(404))
                    : todos.list()
      // DELETE todo
      .delete('/todos/:id', withParams, 
        ({ id }) => todos.remove(id)


Returns a no-body response code.

status(code: number, options?: ResponseInit): Response

return status(204) // returns a 204, without a body


Extends Error, adding an HTTP status code to the constructor. Throwing this is identical to a standard Error, but allows downstream handlers to add context to the error Response.

StatusError(statusCode: number, message?: string): StatusError

throw new StatusError(400, 'Incorrect number of parameters')


Returns a text Response

text(data, options?: ResponseInit): Response

webp new in v4.x

Returns a webp Response

webp(data, options?: ResponseInit): Response

withContent (middleware)

If a request body is attached, this middleware attempts to parse it (as JSON) and embed it within the Request as request.content. See example:

withContent(): void

import { Router, withContent } from 'itty-router'

const router = Router()

  .post('/foo', withContent, 
    ({ content }) => `Your bar is a ${}.`

// POST { bar: 'baz' } to /foo results in
// "Your bar is a baz."

withCookies (middleware)

Extracts cookies from the headers into a cookies object on the Request. See example:

withCookies(): void

import { Router, error, withCookies } from 'itty-router'

const router = Router()

  .get('/foo', withCookies, 
    ({ cookies }) => {
      if (!cookies.Authorization) {
        return error(401)

      // do something

withParams (middleware)

Extracts route params into the Request itself, for convenience. The example shows route params with and without this middleware. This becomes more useful with more route params, or when using withParams as a global upstream middleware, to avoid middleware duplication within each route.

withParams(): void

import { Router, error, withParams } from 'itty-router'

const router = Router()

  // accessing params from request.params
  .get('/:id', ({ params }) => `Your id is ${}`
  // access params directly from the request
  .get('/:id', withParams, ({ id }) => `Your id is ${id}`)

v4.x changes - withParams may finally be used as a global upstream middleware, saving the many boilerplatey injections throughout your routes. Hooray!