Using ipv6-parse in JavaScript

Parse IPv6 and IPv4 in Node.js or a browser with the WebAssembly API.

The Node.js package and browser API use the same C parser compiled to WebAssembly. If address notation is unfamiliar, start with Reading IPv6 addresses.

Start in Node.js

npm install ipv6-parse

Save this as example.cjs and run node example.cjs. The convenience functions load WebAssembly on first use and return promises.

const ipv6 = require('ipv6-parse');

async function main() {
    const addr = await ipv6.parse('[fe80::7/64%eth0]:8080');
    console.log(addr.formatted); // [fe80::7/64%eth0]:8080
    console.log(addr.port);      // 8080
    console.log(addr.mask);      // 64
    console.log(addr.zone);      // eth0
}

main().catch(console.error);

Initialize once for synchronous parsing

Await createParser() at startup, then call methods on its parser synchronously. This avoids a promise for every address in a loop.

const ipv6 = require('ipv6-parse');

async function main() {
    const { parser } = await ipv6.createParser();
    for (const input of ['2001:db8::7', '::1', '192.0.2.1']) {
        const addr = parser.tryParse(input);
        console.log(addr === null ? 'Invalid address' : addr.formatted);
    }
}

main().catch(console.error);

createParser() returns an object containing the parser, classes, and a synchronous functional API named ipv6. After initialization, getParser() and getAPI() return the cached objects; they throw if called before initialization.

Use the same parser in a browser

Download the WebAssembly archive from the releases, or build it with ./build_wasm.sh. Place both JavaScript files beside this HTML page.

<!DOCTYPE html>
<html lang="en">
<meta charset="utf-8">
<title>Parse an IPv6 address</title>
<pre id="output">Loading…</pre>
<script src="ipv6-parse.js"></script>
<script src="ipv6-parse-api.js"></script>
<script>
const output = document.getElementById('output');
createIPv6Module().then(module => {
    const parser = new IPv6Parser(module);
    try {
        output.textContent = parser.parse('[::1]:8080').formatted;
    } finally {
        parser.destroy();
    }
}).catch(error => { output.textContent = error.message; });
</script>
</html>

Module loading is asynchronous; methods on the initialized parser are synchronous. The demo uses this setup. Browser globals and the Node.js package have different initialization steps, but expose the same parser methods.

Read a parsed result

parse() returns an IPv6Address. Missing optional fields are null, so use addr.port !== null or addr.hasPort rather than a truthiness check. A present port or mask can be zero.

PropertyValue
formattedFormatted text; includes IPv6 mask, zone, and port when supplied.
componentsEight numeric 16-bit components, returned as an array copy.
port, maskNumber or null.
zoneString or null.
hasPort, hasMaskWhether those fields were supplied.
isIPv4EmbeddedDotted IPv4 was embedded in IPv6.
isIPv4CompatiblePlain IPv4 input, such as 192.0.2.1.

getComponentHex(index) returns a four-digit hexadecimal group. toString() returns formatted; toJSON() returns a plain object for serialization. Plain IPv4 results retain a parsed CIDR mask in mask, but currently omit it from formatted.

Results contain copies of the values read from WebAssembly, including zone text. You can keep a result after another parse or after releasing the parser's buffers.

Choose how to handle invalid input

MethodInvalid input
parse(input)Throws IPv6ParseError.
tryParse(input)Returns null.
isValid(input)Returns false.

The package-level versions return promises with the same results; a thrown parse error becomes a rejection. For diagnostics, get the error class after initialization:

const ipv6 = require('ipv6-parse');

async function main() {
    const { parser, IPv6ParseError } = await ipv6.createParser();
    try {
        parser.parse('2001:gggg::7');
    } catch (error) {
        if (!(error instanceof IPv6ParseError)) throw error;
        console.error(error.getDetailedMessage());
    }
}

main().catch(console.error);

The error includes message and input. When native diagnostics are available, it also includes diagnostic, position, and event. Empty or non-string input may have no native diagnostic. tryParse() and isValid() still propagate errors unrelated to parsing.

Compare parsed values

const ipv6 = require('ipv6-parse');

async function main() {
    const { parser } = await ipv6.createParser();
    console.log(parser.equals('::1', '0:0:0:0:0:0:0:1')); // true
    console.log(parser.equals('[::1]:80', '[::1]:443')); // false
    console.log(parser.equals('[::1]:80', '[::1]:443', {
        ignorePort: true
    })); // true
}

main().catch(console.error);

Use ignorePort or ignoreMask to exclude that field. The runtime also accepts ignoreFormat to compare plain and embedded IPv4 forms. Comparison is not a subnet-membership test; invalid address strings compare unequal.

Zone IDs are always excluded by the underlying comparison. If interface identity matters, parse both inputs and also compare a.zone === b.zone. There is no option that enables zone comparison.

Parser lifetime

A parser allocates and reuses WebAssembly buffers. Call parser.destroy() when the owner is done with it. Node.js caches a shared parser, so coordinate cleanup with other users of that parser. Browser code that constructs its own parser owns that instance.

getVersion() reports the library version. The development guide covers WebAssembly builds, tests, and benchmarks. For typed application code, continue with the TypeScript guide.