# neosemantics is the plugin that lets Neo4j hold RDF without flattening it

> neosemantics, the n10s plugin from the Neo4j Labs team, adds RDF to a Neo4j instance: it imports triples into the property graph in a lossless way, exports a property graph back out as RDF on demand, validates a model against the W3C SHACL language, and loads OWL, RDFS and SKOS ontologies. It is a Maven project with a jar you drop into the plugins directory, and the README is a working tutorial rather than a brochure.

**neo4j-labs/neosemantics** — Graph+Semantics: Import/Export RDF from Neo4j. SHACL Validation, Model mapping and more.... If you like it, please ★ ⇧

- Repository: https://github.com/neo4j-labs/neosemantics
- Website: https://neo4j.com/labs/neosemantics/
- Stars: 970 · Forks: 154
- Language: Java
- License: Apache-2.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/neo4j-labs-neosemantics

## A labs project with a disclaimer at the top

The first line of the README is the one to read before anything else, this is an experimental Neo4j Labs project and not part of Neo4j's supported product lineup, with a link to the Labs disclaimer file that sits in the repository root. That framing is not a formality in this ecosystem, where the Labs projects are where the interesting but unproven work happens and where the difference between a supported plugin and an experimental one shows up in your incident response. The rest of the project is a plugin called n10s, short for neosemantics, that enables the use of RDF in Neo4j, and RDF is the W3C standard model for data interchange. The implementation is Java in a Maven project, with a `pom.xml`, a `src/` directory and a `license.txt` carrying the Apache-2.0 terms, and the release history shows the version scheme follows Neo4j's own calendar releases, with 2025.06.1 published in June 2026 and 5.26.0 and 5.20.0 before it.

## Lossless import and export is the point of the whole thing

The feature list leads with the property that matters. RDF data can be stored in Neo4j in a lossless manner, and the documentation spells out what that means, that imported RDF can subsequently be exported without losing a single triple in the process. The second feature is the mirror image, on-demand export of property graph data as RDF, so a graph that never held RDF in the first place can be published as RDF without a separate export pipeline. The third is model validation based on the W3C SHACL language, which is the standard way of stating constraints on a graph and checking them, and the fourth is the import of ontologies and taxonomies in OWL, RDFS, SKOS and the rest, which is how the vocabulary behind the data arrives. The README also mentions model mapping and inferencing over Neo4j graphs as other things the project covers, which is the hint that this is a two way bridge rather than a one way importer.

## Installing means a jar and one line of configuration

There are two install routes and they are the same two steps. On Neo4j Desktop you select your database, go to the plugins section and click install, and the most up to date compatible version is shown for you. On a server you download the jar from the releases area and copy it into the `<NEO_HOME>/plugins` directory, then add a line to `<NEO_HOME>/conf/neo4j.conf` and restart the server. The configuration line is the same in both cases, and it is what mounts the HTTP endpoint:

```
server.unmanaged_extension_classes=n10s.endpoint=/rdf
```

The Desktop route reaches the same setting through the three dots to the right of the database name and then settings, where the fragment can be appended to the file. The `unmanaged_extension_classes` key is a Neo4j mechanism for hosting an HTTP endpoint from a plugin rather than from the server itself, and the path after the equals sign is where the endpoint lives. If you only want the procedures and not the endpoint, the configuration line is the part you leave out, which is a distinction worth making before you expose an HTTP surface on a database.

## Verifying the install is two queries and a log line

The documentation tells you how to check that the work went well, and the checks are specific. The first is a procedure listing:

```
SHOW PROCEDURES WHERE name STARTS WITH "n10s"
```

The list should contain a number of procedures with the `n10s` prefix. The second check is the log, where the server should show this line on startup if the endpoint was mounted:

```
YYYY-MM-DD HH:MM:SS.000+0000 INFO  Mounted unmanaged extension [n10s.endpoint] at [/rdf]
```

And the third is a request from the Neo4j browser, where `:GET /rdf/ping` should return:

```
{"ping":"here!"}
```

Three checks that between them tell you whether the jar was found, whether the configuration was read and whether the endpoint is live. That is a more careful verification procedure than most plugin documentation offers, and it is the sort of detail that matters when the plugin runs inside a database rather than beside it.

## The GraphConfig is where the mapping decisions are made

Before any import, a GraphConfig has to exist, and this is the object that decides how RDF becomes a property graph. The defaults can be created with a single call, `call n10s.graphconfig.init()`, or you can pass a map of options to the same procedure. The options are where the judgement is, and the documentation tabulates them. `handleVocabUris` takes SHORTEN, KEEP, SHORTEN_STRICT or MAP and decides how namespaces are handled, which is the question of whether a URI is stored in full or abbreviated, and whether the abbreviation is reversible. `handleMultival` takes OVERWRITE or ARRAY and decides how multivalued properties are handled, which is the question of whether several values for the same predicate become a list or overwrite each other. `handleRDFTypes` takes LABELS, NODES or LABELS_AND_NODES and decides how RDF datatypes are handled, whether a type becomes a node label, a node, or both. And `multivalPropList` is a list of predicate URIs to which the multivalued handling applies specifically. The full list is in the reference documentation, and the decision is worth making consciously, because a property graph cannot hold everything RDF can express.

## Importing from a URL or from a string

The import step comes in two forms and the naming is consistent across the plugin. To fetch from a URL you use `n10s.rdf.import.fetch` with the address and the syntax, for example:

```
call n10s.rdf.import.fetch( "https://raw.githubusercontent.com/jbarrasa/neosemantics/3.5/docs/rdf/nsmntx.ttl",
                            "Turtle")
```

To pass the data yourself you use `n10s.rdf.import.inline` with a payload string, and the call yields four things, `terminationStatus`, `triplesLoaded`, `triplesParsed` and `namespaces`, which is exactly the set of numbers you want to see in a log, since the difference between the triples parsed and the triples loaded tells you what the mapping rejected. You can also pass request specific parameters such as `headerParams`, `commitSize` and `languageFilter`, and the same naming scheme applies to the other namespaces of the plugin, so ontologies are imported with `n10s.onto.import.fetch`. One step comes before all of this, and it is not optional. The README lists it as step zero, the creation of a constraint:

```
CREATE CONSTRAINT n10s_unique_uri FOR (r:Resource) REQUIRE r.uri IS UNIQUE
```

The import depends on that constraint, because the resource URI is the identity of a node and has to be unique for the round trip to be lossless.

## What to check before this goes near production

Two things stand out for anyone considering the project seriously. The first is the version scheme, because it tells you the plugin tracks the Neo4j release calendar, with the release names carrying the year and month, and the default branch is `2025.06` to match. That is a sensible scheme for a plugin that uses server internals, and it also means an upgrade of Neo4j is an upgrade decision for this plugin as well, not an independent one. The second is the documentation's own hedging, that full documentation will be available soon, and the invitation to share feedback in the Neo4j community portal. Combined with the Labs disclaimer, the picture is of a capable and actively maintained bridge that a production team should treat with the caution the disclaimer asks for, testing the round trip on your own data rather than assuming the lossless claim holds for your vocabulary. The blog the project links is a better source of worked examples than the README, and the reference documentation is where the full option list lives.

## Conclusion

neosemantics suits a team with both a property graph and an RDF world who need the two to meet, since the lossless import and the on-demand export are the features that make the round trip possible, and the SHACL validation gives the imported data a standard way to be checked. It is a poor fit if you need a supported product, because the README opens by saying it is an experimental Neo4j Labs project and not part of Neo4j's supported product lineup, and it is a poor fit if you want schema evolution to be automatic, since the mapping decisions are yours to make in the GraphConfig. Before you put it into a production graph, check three things: the constraint the README asks for, which the import depends on, the GraphConfig settings, which decide how namespaces, multivalued properties and RDF types are persisted, and the version you deploy, with 2025.06.1 published on 2026-06-16 and the last push to the repository on 2026-10-09.

## FAQ

### What does neosemantics do for Neo4j?

It is the n10s plugin that enables the use of RDF in Neo4j. It stores RDF in a lossless way so that imported triples can be exported again without losing any, exports property graph data as RDF on demand, validates models against the W3C SHACL language, and imports ontologies and taxonomies in OWL, RDFS and SKOS.

### How do I install the neosemantics plugin?

On Neo4j Desktop, select the database and install it from the plugins section. On a server, copy the jar from the releases area into the `<NEO_HOME>/plugins` directory, add `server.unmanaged_extension_classes=n10s.endpoint=/rdf` to `<NEO_HOME>/conf/neo4j.conf` and restart the server.

### How do I check that neosemantics is installed?

Run `SHOW PROCEDURES WHERE name STARTS WITH "n10s"` and look for the prefixed procedures, check the server log for the line reporting that the unmanaged extension was mounted at /rdf, and try `:GET /rdf/ping` in the Neo4j browser, which returns a ping message.

### What are the neosemantics GraphConfig options?

handleVocabUris decides how namespaces are handled with SHORTEN, KEEP, SHORTEN_STRICT or MAP, handleMultival decides how multivalued properties are handled with OVERWRITE or ARRAY, handleRDFTypes decides how RDF datatypes are handled with LABELS, NODES or LABELS_AND_NODES, and multivalPropList names the predicate URIs the multivalued handling applies to.

### Is neosemantics a supported Neo4j product?

No. The README states it is an experimental Neo4j Labs project and not part of Neo4j's supported product lineup, with a disclaimer file in the repository. The releases follow the Neo4j calendar, with 2025.06.1 published on 2026-06-16 and the last push to the repository on 2026-10-09.

## Sources

- [License: Apache-2.0](https://github.com/neo4j-labs/neosemantics/blob/2025.06/LICENSE)
- [neo4j-labs/neosemantics on GitHub](https://github.com/neo4j-labs/neosemantics)
- [Project website](https://neo4j.com/labs/neosemantics/)
- [README](https://github.com/neo4j-labs/neosemantics/blob/2025.06/README.md)
- [Releases](https://github.com/neo4j-labs/neosemantics/releases)

---

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