swagger-parser: validating and dereferencing OpenAPI documents
Swagger 2.0 and OpenAPI 3.0 parser/validator
At a glance
- What is it?
- The JavaScript library from APIDevTools parses Swagger 2.0 and OpenAPI 3.0 documents, resolves every $ref pointer, and can bundle or dereference a spec into something your code can use. It also resolves referenced files by default, which is the one thing you must think about before pointing it at an untrusted document.
- Who is it for?
- Adopt swagger-parser when your Node service needs to turn an OpenAPI document into a validated, dereferenced object at startup, and when you want one parser for both Swagger 2.0 and OpenAPI 3.0 instead of maintaining two.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One library for Swagger 2.0 and OpenAPI 3.0
swagger-parser is a JavaScript package published as @apidevtools/swagger-parser, and it does four related jobs on an API description document. It parses specs written in JSON or YAML. It validates them against the Swagger 2.0 schema or the OpenAPI 3.0 schema. It resolves all $ref pointers, including references to external files and URLs. And it can hand you the result in whichever shape your code needs.
The last point is where the library earns its place. Many consumers of an OpenAPI document want one of three things, and the package exposes all three without asking you to write the transformation yourself.
Bundling takes a multi-file specification and produces a single file whose only remaining $ref pointers are internal ones. Dereferencing goes further and gives you a normal JavaScript object with the references expanded, which is the form you want when you are generating client code, validating payloads or writing mock handlers. Validation alone is useful when you have a CI job that should fail on a malformed spec. The library keeps the original, the bundled and the dereferenced forms available through the same API, so a pipeline can parse once and consume the shape that suits each step.
The repository also lists two sibling projects from the same maintainers, Swagger CLI and Swagger Express Middleware, which matter when you are deciding what to build yourself.
Reference equality is the detail that saves you later
One of the more useful guarantees in the library is not about schemas at all. The documentation states that the parser maintains object reference equality, meaning that $ref pointers to the same value always resolve to the same object instance. In practice that means two paths in your document that point at one shared definition end up as one object in memory, not two copies that happen to look alike.
This matters more often than it sounds. A generator that walks a dereferenced document can cache results per object identity, and equality checking by reference is dramatically cheaper than deep comparison when the document has hundreds of shared components. It also removes a class of subtle bug where a mutation applied through one path appears not to affect the other, which is exactly the confusion that appears when a payload validator silently ignores a change made to a shared schema.
The parser also handles the hard reference cases the documentation calls out: circular references, nested references, back-references and cross-references. Circular structures are the reason many hand-rolled resolvers give up, because a naive depth-first walk never terminates on them. Having that handled in a maintained library removes a category of work from any tool that ingests third party specifications, and the project reports testing across more than 1,500 real world APIs from services including Google, Microsoft, Facebook and Spotify, with coverage of the specification types found there rather than a single happy path fixture.
Installing it and making the first call
Installation is a single npm package, and the runtime floor is explicit:
npm install @apidevtools/swagger-parserNode.js 22.19 or later is required, and the package manifest carries that as an engines constraint of node >=22.19.0. In a plain Node.js application the CommonJS form is the common choice:
const SwaggerParser = require("@apidevtools/swagger-parser");If you are using a transpiler such as Babel or TypeScript, or a bundler such as Webpack or Rollup, the ECMAScript modules form works instead:
import * as SwaggerParser from "@apidevtools/swagger-parser";The first real use is a validation call, and the library supports both callback and promise style. The callback form:
SwaggerParser.validate(myAPI, (err, api) => {
if (err) {
console.error(err);
} else {
console.log("API name: %s, Version: %s", api.info.title, api.info.version);
}
});And the same thing with async and await:
try {
let api = await SwaggerParser.validate(myAPI);
console.log("API name: %s, Version: %s", api.info.title, api.info.version);
} catch (err) {
console.error(err);
}The result on success is the API object itself, which is why the example reads api.info.title and api.info.version straight after the call.
The resolver will fetch files it thinks are referenced
The security section of the documentation deserves more attention than it usually gets, and it is the reason this library should not be pointed at arbitrary documents by default.
By default, the library attempts to resolve any file referenced using $ref, without considering the extension of the file or where it is located. The documentation states plainly that this can result in Local File Inclusion, and therefore potentially sensitive information disclosure. The consequence is concrete: if you validate a specification that an attacker wrote, a $ref pointing at something like a local configuration file may be read and folded into the resolved document, and whatever your application does with the result, an error message or a generated artefact, may leak.
The advice given is to be cautious with documents from untrusted sources, and SECURITY.md exists to describe the issue in more detail and how to mitigate it. There is no allowlist of hosts in the default behaviour described here, which means the mitigation has to come from the calling side: validating a document you did not write should happen in a process with restricted filesystem access, and any configuration that restricts what the resolver may reach has to be set by you.
This is a design trade-off, and it is defensible for a tool whose normal job is to load a specification the developer trusts from their own repository. It becomes the deciding factor the moment you add a service that accepts a URL or an uploaded file and parses it.
Browser use means a bundler, not a script tag
The library is described as tested in Node.js and in all modern web browsers on Mac, Windows and Linux, and the topics list universal-javascript for a reason. The catch is that browsers do not read node_modules, so a browser build needs packaging work.
The documentation is specific about that: you need a bundling tool such as Webpack, Rollup, Parcel or Browserify, and some bundlers need a little configuration, such as setting browser: true in rollup-plugin-resolve. Older browsers may require Babel and polyfills, and the project ships an esbuild plugin for polyfilling node in its devDependencies, which tells you what the awkward edge of that support is.
There is also a separate karma.conf.js in the repository, so the browser build is exercised by its own test setup rather than assumed to work. If you only need validation in the browser, the dependency surface is small enough that a bundler setup is the main cost. If you need dereferencing with external references in the browser, the resolver has to fetch those references from the page's origin, which is another thing to plan for.
The library also ships its own type definitions, with typings pointing at lib/index.d.ts and a separate TypeScript test that compiles the definition file under strict mode. The published files list includes only lib, so the types travel with the package.
Swapping the parser for the CLI or the Express middleware
The two related projects from APIDevTools cover the cases where you would otherwise wrap the parser yourself, and the difference in approach is worth spelling out.
Swagger CLI is the command line route. It is listed as a related project for the cases where a command line interface is a better fit than a script in your own codebase, such as a CI pipeline or a build step. The parser remains the engine; the CLI is the packaging.
Swagger Express Middleware is the serving route. Instead of parsing a specification and routing requests yourself, you mount middleware in an Express application instead of wiring the routes yourself. The two are listed as separate packages rather than features inside the parser itself.
For a project that needs the parsed object and nothing else, the parser on its own is the smallest dependency. Reach for the CLI when a shell is the interface you need, and for the middleware when the specification should be part of a running API. The parser is also the sensible building block if you want neither of those shapes, since it exposes parse, validate, bundle and dereference as separate operations rather than forcing one pipeline.
A fast release line and a specific runtime floor
The project is not archived and the last push was on 2026-09-20. The recent release history shows a major version landing in early September 2026, v13.0.0 on 2026-09-02, followed by v13.1.0 on 2026-09-20, with v12.1.0 before that on 2025-10-14. A major bump in the 13 series is the kind of change that deserves reading of the changelog before you take it, since a parser that changes its default resolution behaviour is exactly the kind of library where a silent default change can alter what your application fetches.
The licence is MIT, and the project says so plainly: free and open source, use it however you want. There is one extra request layered on top, which is that the package is Treeware, and the maintainers ask that you buy the world a tree if you use it in production. That is a request rather than a licence condition, and it is worth knowing about because it is unusual enough that a procurement conversation may raise it.
Contributing is straightforward, and the development requirements are specific: use the current Node.js LTS release, and note that the TypeScript tests use the TypeScript 7 compiler while ESLint uses the TypeScript 6 compatibility API through Microsoft's recommended package aliases. The local test loop is pnpm install, pnpm test, and pnpm run coverage, with mocha and nyc behind them. The package is built on pnpm with a pnpm-workspace.yaml at the root, and a CHANGELOG.md is present for anyone upgrading across the 12 to 13 boundary.
Editorial conclusion
Adopt swagger-parser when your Node service needs to turn an OpenAPI document into a validated, dereferenced object at startup, and when you want one parser for both Swagger 2.0 and OpenAPI 3.0 instead of maintaining two. Do not adopt it as a validator for documents you did not author without reading SECURITY.md first, because the library resolves referenced files without regard to extension or location, and treat the browser build as a bundler problem rather than a drop-in script. Before you start, check that your runtime is on Node 22.19 or later, that the version you install matches the specification you need, and that your CI has a rule about which hosts the resolver is allowed to reach when external $ref URLs are in play.
Frequently asked questions
What is the difference between bundling and dereferencing in swagger-parser?
Bundling combines all your Swagger files into a single file that keeps only internal $ref pointers, while dereferencing expands every $ref pointer so you end up with a plain JavaScript object that is easy to work with. The same library exposes both operations.
Is it safe to validate an OpenAPI document from an untrusted source?
Not without care. By default the library resolves any file referenced with $ref without considering file extensions or location, which the documentation says can result in Local File Inclusion and sensitive information disclosure, so it advises caution with untrusted documents and points to SECURITY.md for mitigation.
What Node.js version does swagger-parser need?
Node.js 22.19 or later is required, and the package manifest expresses that as an engines constraint of node >=22.19.0. The same applies to the CommonJS require form and the ES module import form.
Can swagger-parser handle a specification with circular references?
Yes. The documentation lists circular references among the supported cases, together with nested references, back-references and cross-references, and the project reports being tested on more than 1,500 real world APIs.
How do I use swagger-parser in a browser?
You need a bundling tool such as Webpack, Rollup, Parcel or Browserify, and some bundlers need configuration such as setting browser: true in rollup-plugin-resolve. Older browsers may need Babel and polyfills, and the project is tested in recent versions of every major browser.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/apidevtools-swagger-parser)Was this useful?