# @koa/bodyparser, the request body parser Koa leaves to you

> @koa/bodyparser is the Koa middleware that turns an incoming request body into ctx.request.body, handling json, form, text and xml with per type size limits and a strict JSON mode. It is built on co-body, it refuses multipart on purpose, and its options are the interesting part of the API.

**koajs/bodyparser** — Koa body parsing middleware

- Repository: https://github.com/koajs/bodyparser
- Stars: 1,325 · Forks: 120
- Language: TypeScript
- License: MIT
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/koajs-bodyparser

## Koa gives you the context, not the body

Koa is a minimal web framework, and it deliberately does not include body parsing middleware, so an application that accepts POST requests has to add one. @koa/bodyparser is the official one, and it is described as Koa body parsing middleware based on co-body, supporting the json, form and text body types. The mechanism is a middleware that parses the incoming request body before your handlers run and puts the result on the ctx.request.body property. The usage example in the README shows the whole contract, since the application registers the middleware and then reads the parsed body from the context.

```js
const Koa = require("koa");
const { bodyParser } = require("@koa/bodyparser");

const app = new Koa();
app.use(bodyParser());

app.use((ctx) => {
  // the parsed body will store in ctx.request.body
  // if nothing was parsed, body will be an empty object {}
  ctx.body = ctx.request.body;
});
```

The empty object default is worth noting, because a handler that assumes an absent body is null will meet an object instead. The audience is every Koa developer who has written a handler and found ctx.request.body undefined, and the decision is a dependency and a set of limits rather than a framework change.

## Installing it, and the two dist files

The package is on npm under the scoped name, and the install command in the README is the only step.

```bash
$ npm i @koa/bodyparser --save
```

The package metadata shows a modern dual module layout, with main pointing at ./dist/index.js for CommonJS, module at ./dist/index.mjs for ES modules, and types at ./dist/index.d.ts, and an exports map that routes require and import to the two different files. The build itself is tsup, and the published files list contains only dist, so the source and the test setup stay out of the tarball. The peer dependency is koa at 2 or newer, and the engines field requires Node 18 or newer. The runtime dependencies are small and tell you what the middleware actually does: co-body does the parsing, type-is does the content type detection, and lodash.merge combines the options with the defaults. There is also @types/co-body in the dependency list, which is an unusual choice and suggests the typings are partly hand maintained rather than generated from the upstream.

## The options that decide what gets parsed at all

Four options decide the shape of the middleware's behaviour. enableTypes lists the request types the parser will handle, supporting json, form, text and xml, and it defaults to json and form only, so a text or xml body is not parsed unless you ask for it. parsedMethods declares the HTTP methods whose bodies are parsed and defaults to POST, PUT and PATCH, which means a DELETE with a body is ignored, and it also means a body on a GET is ignored. encoding sets the requested encoding and defaults to utf-8, a value that comes from co-body. Then there are the limits, and they are per type rather than global. formLimit is 56kb, jsonLimit, textLimit and xmlLimit are each 1mb, and if the body is larger than its limit the middleware returns a 413 error code. The practical consequence for an API is that the defaults are conservative for file-ish payloads and generous for JSON, and that a 413 is the shape of failure your clients will see when they post something too large.

## Strict JSON by default, and hooks for the unusual cases

jsonStrict is on by default, and the README explains the reasoning in a sentence worth keeping. When it is true the JSON parser only accepts arrays and objects, so ctx.request.body is always an object or an array and handlers avoid a lot of type judging, while a text body always returns a string. If a client posts a bare JSON scalar, it is rejected rather than silently becoming a string in one place and an object in another. Four more options cover the cases where the defaults do not fit. detectJSON takes a custom function to decide whether a request is JSON, defaulting to null, and the example tests the path.

```js
app.use(
  bodyParser({
    detectJSON(ctx) {
      return /\.json$/i.test(ctx.path);
    }
  })
);
```

extendTypes adds content types to an existing parser, so a body of type application/x-javascript can be parsed as a JSON string. patchNode patches the request body into Node's ctx.req and defaults to false. enableRawChecking, also false by default, lets an already parsed body on the raw request override the sent payload, and disableBodyParser can be set per request, so ctx.disableBodyParser = true turns parsing off for one route without unmounting the middleware.

## Custom error responses and the raw body escape hatch

onError lets an application replace the default response when parsing fails, and the example shows the shape.

```js
app.use(
  bodyParser({
    onError(err, ctx) {
      ctx.throw(422, "body parse error");
    }
  })
);
```

That matters because the default failure is a status code without much detail, while 422 with a message is what a client can act on. Separately, the raw body is reachable through ctx.request.rawBody, and the README states the two conditions under which it exists. The middleware must have parsed the request, and ctx.request.rawBody must not have been present before the middleware ran. So it is a property of the parse, not a general way to read the wire format, and a handler that needs the exact bytes should reach for it before the body parser runs or use the raw request stream instead. There is also a documented dynamic disable, where a middleware sets ctx.disableBodyParser = true for a given path and then calls next, with the body parser registered after it.

## Koa 1.x users need a different package

The README keeps a separate section for the old framework line, and it is the kind of note that saves an afternoon. To use bodyparser with koa 1.x.x you should use bodyparser 2.x, installed under the unscoped name.

```bash
$ npm install koa-bodyparser@2 --save
```

The usage is the same shape as the current package, with the middleware registered and the body read from ctx.request.body, so the migration is mostly a change of import path. The reason the split exists is that the scoped @koa/bodyparser package targets Koa 2 and above, and the peer dependency in the package metadata says so explicitly, with koa at 2 or newer. The current version is 6.1.0, published on 2026-01-24, and it follows 6.0.0 from 2025-06-05 and 5.1.1 from 2024-04-08, so the major line has moved on twice since the 5.x series, and an application still on 5.x should read the changelog before bumping.

## A small TypeScript package with three example flavours

The repository layout is compact, which suits a package this focused. src/ holds the implementation, test/ the test suite, and examples/ is split into cjs, esm and typescript directories, which is a good sign because it means the three consumption styles the package advertises are actually exercised. The build uses tsup, the tests run under jest with the --detectOpenHandles flag, the linting is xo with a custom xo-config.json, and the git hooks come from a .huskyrc. The test dependencies tell you how the middleware is verified, with supertest driving HTTP requests against a Koa app and koa at 3.1.1 as the framework under test, plus ts-jest and ts-node for the TypeScript sources. A History.md file at the root is where the release notes live. The licence is MIT, which is what you would expect for a package that most applications will never modify, and the repository is not archived with the last push on 2026-08-03, so the maintenance picture is a normal one: a maintained dependency with a permissive licence and a documented option surface.

## Conclusion

Koa bodyparser fits a Koa service that accepts JSON or form submissions and wants the parsed result as a plain object on the context, with limits that keep a large payload from reaching a handler. It does not fit an upload endpoint, since the project states plainly that multipart is not supported and points to @koa/multer for that, and it does not fit a service that needs a body parsed for methods outside the default list. Verify three things before you wire it in: which content types your clients actually send, because enableTypes defaults to json and form only, and a text or xml body will not be parsed unless you ask for it, what the right size limits are for your endpoints, since the defaults of 56kb for forms and 1mb for the others are small for some payloads and a request over the limit returns 413, and whether the strict JSON mode suits your clients, because jsonStrict is on by default and rejects a bare JSON scalar.

## FAQ

### How do I install and use @koa/bodyparser?

Install it with npm i @koa/bodyparser --save, then register the middleware with app.use(bodyParser()). The parsed result is available on ctx.request.body, and it is an empty object when nothing was parsed.

### Does @koa/bodyparser handle file uploads?

No. The README states that the module does not support parsing multipart format data and points to @koa/multer for that. It handles json, form, text and xml, with json and form enabled by default through the enableTypes option.

### What are the default body size limits?

formLimit defaults to 56kb, and jsonLimit, textLimit and xmlLimit each default to 1mb. If a body is larger than its limit the middleware returns a 413 error code, and each limit can be overridden in the options.

### Which HTTP methods does @koa/bodyparser parse?

The parsedMethods option declares them and defaults to POST, PUT and PATCH. A body sent with a method outside that list is not parsed, and the option can be changed to widen the set.

## Sources

- [Issues](https://github.com/koajs/bodyparser/issues)
- [koajs/bodyparser on GitHub](https://github.com/koajs/bodyparser)
- [License: MIT](https://github.com/koajs/bodyparser/blob/master/LICENSE)
- [README](https://github.com/koajs/bodyparser/blob/master/README.md)
- [Releases](https://github.com/koajs/bodyparser/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/koajs-bodyparser
