fast-xml-parser, xml-js, xml-parser, and xml2js are npm packages designed to parse XML strings into JavaScript objects or convert JavaScript objects back into XML. These libraries help frontend and full-stack developers handle XML data—commonly used in legacy APIs, configuration files, or enterprise integrations—within modern JavaScript environments. Each package offers different trade-offs in parsing strictness, performance, feature set, and ease of use.
When you’re stuck dealing with XML—whether from a SOAP API, an old config file, or a third-party feed—you’ll likely reach for an npm package to turn that markup into something JavaScript can actually work with. Among the popular choices are fast-xml-parser, xml-js, xml2js, and the outdated xml-parser. Let’s cut through the noise and compare them based on real engineering concerns: correctness, performance, API design, and maintainability.
Before diving deep, note this critical fact:
xml-parser is deprecated. Its npm page explicitly states: "This module is deprecated. Please use xml2js instead." It hasn’t been updated since 2015, lacks namespace support, fails on many valid XML inputs, and should not be used in any new project.We’ll focus the rest of this comparison on the three actively maintained alternatives.
All three usable packages convert XML strings into plain JavaScript objects—but they do it differently.
fast-xml-parserUses a recursive descent parser. By default, it preserves attribute names under a @_ prefix and text content under #text. You can disable attributes or change parsing behavior via options.
// fast-xml-parser
import { parse } from 'fast-xml-parser';
const xml = `<book id="101"><title>JS Guide</title></book>`;
const result = parse(xml);
// { book: { '@_id': '101', title: 'JS Guide' } }
xml-jsOffers two modes: element (tree-like with type metadata) and javascript (simpler object). The latter is more common for app logic.
// xml-js
import { xml2js } from 'xml-js';
const xml = `<book id="101"><title>JS Guide</title></book>`;
const result = xml2js(xml, { compact: true });
// { book: { _attributes: { id: '101' }, title: 'JS Guide' } }
xml2jsUses the sax parser under the hood and relies on callbacks (though promisified versions exist). Attributes go into a $ property by default.
// xml2js
import { parseStringPromise } from 'xml2js';
const xml = `<book id="101"><title>JS Guide</title></book>`;
const result = await parseStringPromise(xml);
// { book: { $: { id: '101' }, title: [ 'JS Guide' ] } }
💡 Notice how
xml2jsalways wraps child text in arrays—even for single elements. This avoids ambiguity but adds noise.
Sometimes you need to generate XML from data (e.g., for API requests). Only two of these support reliable round-trip conversion.
fast-xml-parserIncludes a parse and unparse pair. The output closely matches input if you preserve structure.
// fast-xml-parser: round-trip
import { parse, unparse } from 'fast-xml-parser';
const xml = '<note><to>Alice</to></note>';
const obj = parse(xml);
const backToXml = unparse(obj);
// "<note><to>Alice</to></note>"
xml-jsAlso supports bidirectional conversion cleanly.
// xml-js: round-trip
import { js2xml, xml2js } from 'xml-js';
const xml = '<note><to>Alice</to></note>';
const obj = xml2js(xml, { compact: true });
const backToXml = js2xml(obj, { compact: true });
// "<note><to>Alice</to></note>"
xml2jsDoes not include a built-in serializer. You’d need a separate package like js2xmlparser—breaking round-trip symmetry and adding maintenance risk.
Real XML isn’t always clean. How do these libraries cope?
Namespaces:
fast-xml-parser supports them out of the box (ignoreNameSpace: false by default).xml-js ignores namespaces unless you use non-compact mode (then they appear as prefix:localName).xml2js supports them via the xmlns option but requires extra config.CDATA:
xml2js may require explicitChildren: true to avoid merging.Whitespace:
fast-xml-parser trims by default (trimValues: true), but you can disable it.xml-js preserves whitespace in compact mode.xml2js keeps all whitespace unless you set normalize: true.While we won’t quote numbers (per instructions), consider these qualitative differences:
fast-xml-parser is written in pure JavaScript with zero dependencies. It’s optimized for speed and works in browsers without polyfills.xml-js is also dependency-free and lightweight, but not tuned for large documents.xml2js depends on the sax parser, which is robust but heavier. It’s primarily designed for Node.js and may bloat browser bundles.fast-xml-parser throws clear errors on malformed XML (e.g., unclosed tags) and offers optional validation.xml-js uses try/catch internally but gives vague error messages like “Invalid character” without context.xml2js emits errors via callbacks or rejects promises, but stack traces can be hard to debug due to sax’s event-driven nature.fast-xml-parser and xml-js work out of the box. xml2js can be bundled but isn’t optimized for it.xml2js is most entrenched in legacy Node ecosystems.| Feature | fast-xml-parser | xml-js | xml2js |
|---|---|---|---|
| Actively maintained | ✅ Yes | ✅ Yes | ✅ Yes |
| Bidirectional | ✅ Parse + unparse | ✅ xml2js + js2xml | ❌ Parse only |
| Zero dependencies | ✅ | ✅ | ❌ (depends on sax) |
| Browser-friendly | ✅ Excellent | ✅ Good | ⚠️ Possible, but heavy |
| Array handling | Single values stay scalar | Single values stay scalar | Always arrays |
| Error clarity | ✅ Clear messages | ⚠️ Generic errors | ⚠️ Hard to trace |
| Namespace support | ✅ Built-in | ⚠️ Limited | ✅ With config |
fast-xml-parser. It’s fast, correct, dependency-free, and handles real-world XML gracefully.xml-js is fine if your data is small and you value compact object shapes.xml2js is acceptable if you’re already using it, but don’t adopt it for new work.xml-parser—it’s obsolete and unsafe.In practice, most teams today will find fast-xml-parser hits the sweet spot: it just works, doesn’t surprise you, and stays out of your way.
Choose fast-xml-parser when you need high-performance XML parsing with minimal memory overhead and support for both browser and Node.js environments. It’s ideal for applications that process large XML documents or require validation against basic XML rules without external dependencies. Its streaming parser and customizable options (like ignoring attributes or preserving order) make it suitable for real-world production systems where speed and correctness matter.
Choose xml2js when working in a Node.js environment and you need mature, battle-tested XML parsing with extensive configuration options (e.g., explicit array coercion, custom tag processors). It’s commonly used in enterprise or legacy integration scenarios but comes with heavier runtime behavior due to its reliance on the sax parser and callback-based design. Not recommended for browser-only apps unless bundled carefully.
Choose xml-js if your primary need is bidirectional conversion between XML and JavaScript objects with a simple, consistent API. It’s well-suited for smaller payloads where readability of the resulting object structure is important, and you don’t require advanced XML features like namespaces or DTDs. Avoid it for performance-critical paths or large documents, as it’s not optimized for speed.
Do not choose xml-parser for new projects — it is deprecated on npm and no longer maintained. The package lacks modern features, has known limitations in handling edge cases, and hasn’t received updates in years. Use fast-xml-parser or xml2js instead depending on your needs.
Validate XML, Parse XML to JS Object, or Build XML from JS Object without C/C++ based libraries and no callback.
It can handle big files (tested up to 100mb). XML Entities, HTML entities, and DOCTYPE entites are supported. Unpaired tags (Eg <br> in HTML), stop nodes (Eg <script> in HTML) are supported. It can also preserve Order of tags in JS object

Sponsor this project

This is a donation. No goods or services are expected in return. Any requests for refunds for those purposes will be rejected.
The list of users are mostly published by Github or communicated directly. Feel free to contact if you find any information wrong.
To use as package dependency
$ npm install fast-xml-parser
or
$ yarn add fast-xml-parser
To use as system command
$ npm install fast-xml-parser -g
To use it on a webpage include it from a CDN
Example
As CLI command
$ fxparser some.xml
In a node js project
const { XMLParser, XMLBuilder, XMLValidator} = require("fast-xml-parser");
const parser = new XMLParser();
let jObj = parser.parse(XMLdata);
const builder = new XMLBuilder();
const xmlContent = builder.build(jObj);
In a HTML page
<script src="path/to/fxp.min.js"></script>
:
<script>
const parser = new fxparser.XMLParser();
parser.parse(xmlContent);
</script>
Bundle size
| Bundle Name | Size |
|---|---|
| fxbuilder.min.js | 6.5K |
| fxparser.min.js | 20K |
| fxp.min.js | 26K |
| fxvalidator.min.js | 5.7K |
| v3 | v4 and v5 | v6 |
| documents |
note:
negative means error
* Y-axis: requests per second
Usage Trend of fast-xml-parser
This project exists thanks to all the people who contribute. [Contribute].
Thank you to all our backers! 🙏 [Become a backer]
