node package manager


Lightning fast, asynchronous, streaming RDF for JavaScript

Build Status Build status Coverage Status npm version DOI

The N3.js library lets you handle RDF in JavaScript easily, in Node.js and the browser. It offers:

Parsing and writing is:

  • asynchronous – triples arrive as soon as possible
  • streaming – streams are parsed as data comes in, so you can parse files larger than memory
  • fast – by far the fastest parser in JavaScript


For Node.js, N3.js comes as an npm package.

$ npm install n3
var N3 = require('n3');

N3.js seamlessly works in browsers. Generate a browser version as follows:

$ cd N3.js
$ npm install
$ npm run browser
<script src="n3-browser.min.js"></script>

In addition, N3.js is fully compatible with browserify, so you can write code for Node.js and deploy it to browsers.

Triple representation

For maximum performance and ease of use, triples are simple objects with string properties.

URLs, URIs and IRIs are simple strings. For example, parsing this RDF document:

@prefix c: <>.
c:Tom a c:Cat.

results in this JavaScript object:

  subject:   '',
  predicate: '',
  object:    ''

Literals are represented as double quoted strings. For example, parsing this RDF document:

c:Tom c:name "Tom".

results in this JavaScript object:

  subject:   '',
  predicate: '',
  object:    '"Tom"'

This allows you to create and compare literals fast and easily:

triple.object === ''
triple.object === '"Tom"'

For literals with a language or type, add a marker (@ or ^^) and the corresponding value as-is:

'"Tom"@en-gb' // lowercase language
'"1"^^' // no angular brackets <>

An optional fourth element signals the graph to which a triple belongs:

  subject:   '',
  predicate: '',
  object:    '"Tom"',
  graph:     ''

The N3.js Utility (N3.Util) can help you with these representations.


From an RDF document to triples

N3.Parser transforms Turtle, TriG, N-Triples or N-Quads document into triples through a callback:

var parser = N3.Parser();
parser.parse('@prefix c: <>.\n' +
             'c:Tom a c:Cat.\n' +
             'c:Jerry a c:Mouse;\n' +
             '        c:smarterThan c:Tom.',
             function (error, triple, prefixes) {
               if (triple)
                 console.log(triple.subject, triple.predicate, triple.object, '.');
                 console.log("# That's all, folks!", prefixes)

The callback's first argument is an error value, the second is a triple. If there are no more triples, the callback is invoked one last time with null for triple and a hash of prefixes as third argument.
Pass a second callback to parse to retrieve prefixes as they are read.
If no callbacks are provided, parsing happens synchronously.

By default, N3.Parser parses a permissive superset of Turtle, TriG, N-Triples and N-Quads.
For strict compatibility with any of those languages, pass a format argument upon creation:

var parser1 = N3.Parser({ format: 'N-Triples' });
var parser2 = N3.Parser({ format: 'application/trig' });

Notation3 (N3) is supported only through the format argument:

var parser3 = N3.Parser({ format: 'N3' });
var parser4 = N3.Parser({ format: 'Notation3' });
var parser5 = N3.Parser({ format: 'text/n3' });

From an RDF stream to triples

N3.Parser can parse Node.js streams as they grow, returning triples as soon as they're ready.
This behavior sets N3.js apart from most other libraries.

var parser = N3.Parser(),
    rdfStream = fs.createReadStream('cartoons.ttl');
parser.parse(rdfStream, console.log);

In addition, N3.StreamParser offers a Node.js stream implementation, so you can transform RDF streams and pipe them to anywhere. This solution is ideal if your consumer is slower, since source data is only read when the consumer is ready.

var streamParser = N3.StreamParser(),
    rdfStream = fs.createReadStream('cartoons.ttl');
streamParser.pipe(new SlowConsumer());
function SlowConsumer() {
  var writer = new require('stream').Writable({ objectMode: true });
  writer._write = function (triple, encoding, done) {
    setTimeout(done, 1000);
  return writer;

A dedicated prefix event signals every prefix with prefix and iri arguments.


From triples to a string

N3.Writer serializes triples as an RDF document. Write triples through addTriple.

var writer = N3.Writer({ prefixes: { c: '' } });
  subject:   '',
  predicate: '',
  object:    '"Tom"'
writer.end(function (error, result) { console.log(result); });

By default, N3.Writer writes Turtle (or TriG for triples with a graph property).
To write N-Triples (or N-Quads) instead, pass a format argument upon creation:

var writer1 = N3.Writer({ format: 'N-Triples' });
var writer2 = N3.Writer({ format: 'application/trig' });

From triples to an RDF stream

N3.Writer can also write triples to a Node.js stream.

var writer = N3.Writer(process.stdout, { prefixes: { c: '' } });
  subject:   '',
  predicate: '',
  object:    '"Tom"'

From a triple stream to an RDF stream

N3.StreamWriter is a writer implementation as a Node.js stream.

var streamParser = new N3.StreamParser(),
    inputStream = fs.createReadStream('cartoons.ttl'),
    streamWriter = new N3.StreamWriter({ prefixes: { c: '' } });

Blank nodes and lists

You might want to use the […] and list (…) notations of Turtle and TriG. However, a streaming writer cannot create these automatically: the shorthand notations are only possible if blank nodes or list heads are not used later on, which can only be determined conclusively at the end of the stream.

The blank and list functions allow you to create them manually instead:

var writer = N3.Writer({ prefixes: { c: '',
                                     foaf: '' } });
writer.addTriple(writer.blank('', '"Tom"@en'),
                   predicate: '',
                   object: ''
                   predicate: '',
                   object: '"Tom"@en',
writer.end(function (error, result) { console.log(result); });

Be careful to use the output of blank and list only once and only as argument to addTriple of the same writer, as return values of these functions are unspecified.


N3.Store allows you to store triples in memory and find them fast.

In this example, we create a new store and add the triples :Pluto a :Dog. and :Mickey a :Mouse.
Then, we find triples with :Mickey as subject.

var store = N3.Store();
store.addTriple('',  '', '');
store.addTriple('', '', '');
var mickey = store.getTriples('', null, null)[0];
console.log(mickey.subject, mickey.predicate, mickey.object, '.');

Addition and deletion of triples/quads

The store provides the following manipulation methods (documentation):

  • addTriple to insert one triple/quad
  • addTriples to insert an array of triples/quads
  • addPrefix to register a prefix (facilitating addition and lookup)
  • addPrefixes to register an array of prefixes
  • removeTriple to remove one triple/quad
  • removeTriples to remove an array of triples/quads
  • createBlankNode returns an unused blank node identifier

Searching triples/quads or entities

The store provides the following search methods (documentation):

  • getTriples returns an array of triples/quads matching the given pattern
  • countTriples counts the number of triples/quads matching the given pattern
  • forEach executes a callback on all matching triples/quads
  • every returns whether a callback on matching triples/quads always returns true
  • some returns whether a callback on matching triples/quads returns true at least once
  • getSubjects returns an array of unique subjects occurring in matching triples
  • forSubjects executes a callback on unique subjects occurring in matching triples
  • getPredicates returns an array of unique predicates occurring in matching triple
  • forPredicates executes a callback on unique predicates occurring in matching triples
  • getObjects returns an array of unique objects occurring in matching triple
  • forObjects executes a callback on unique objects occurring in matching triples
  • getGraphs returns an array of unique graphs occurring in matching triple
  • forGraphs executes a callback on unique graphs occurring in matching triples

All of the above methods also have a variant with the byIRI suffix (e.g., getTriplesByIRI), which skips prefix expansion and is thus faster.


N3.Util offers helpers for IRI and literal representations.
As IRIs are most common, they are represented as simple strings:

var N3Util = N3.Util;
N3Util.isIRI(''); // true

Literals are represented as double quoted strings:

N3Util.isLiteral('"Mickey Mouse"'); // true
N3Util.getLiteralValue('"Mickey Mouse"'); // 'Mickey Mouse'
N3Util.isLiteral('"Mickey Mouse"@en'); // true
N3Util.getLiteralLanguage('"Mickey Mouse"@en'); // 'en'
N3Util.isLiteral('"3"^^'); // true
N3Util.getLiteralType('"3"^^'); // ''
N3Util.isLiteral('""'); // true
N3Util.getLiteralValue('""'); // ''

Note the difference between '' (IRI) and '""' (literal).
Also note that the double quoted literals are not raw Turtle/TriG syntax:

N3Util.isLiteral('"This word is "quoted"!"'); // true
N3Util.isLiteral('"3"^^'); // true

The above string represents the string This word is "quoted"!, even though the correct Turtle/TriG syntax for that is "This word is \"quoted\"!" N3.js thus always parses literals, but adds quotes to differentiate from IRIs:

new N3.Parser().parse('<a> <b> "This word is \\"quoted\\"!".', console.log);
// { subject: 'a', predicate: 'b', object: '"This word is "quoted"!"' }

Literals can be created with createLiteral:

N3Util.createLiteral('My text', 'en-gb');
N3Util.createLiteral('123', '');

Blank nodes start with _:, and can be tested for as follows:

N3Util.isBlank('_:b1'); // true
N3Util.isIRI('_:b1'); // false
N3Util.isLiteral('_:b1'); // false

Prefixed names can be tested and expanded:

var prefixes = { rdfs: '' };
N3Util.isPrefixedName('rdfs:label'); // true;
N3Util.expandPrefixedName('rdfs:label', prefixes); //



The N3.js parser and writer is fully compatible with the following W3C specifications:

In addition, the N3.js parser also supports Notation3 (N3) (no official specification yet).

Pass a format option to the constructor with the name or MIME type of a format for strict, fault-intolerant behavior.

License, status and contributions

The N3.js library is copyrighted by Ruben Verborgh and released under the MIT License.

Contributions are welcome, and bug reports or pull requests are always helpful. If you plan to implement a larger feature, it's best to contact me first.