AR.js — The Simplest Way to get Cross-Browser Augmented Reality on the Web

Updated Version — How to deliver Augmented Reality contents on the web, in an open-source, easy and cross-browser way.

Nicolò Carpignoli
May 11 · 5 min read

This is the first part of a series of articles about AR.js. The following is the list of the articles written so far:

For the latest news about AR.js and Web AR, you can follow me!

Just another AR library?

For those who don’t know it yet, AR.js is a great project with over 13k stars on Github, that makes easy and fun to develop augmented reality apps with web technologies. With a few simple lines of Javascript and some 3D modelling, it’s almost immediate to develop an augmented reality web-app.

Amongst its most interesting characteristics:

  • Performance, ~60 FPS on my two-year-old phone (!)
  • Compatibility, it is cross-browser, it works on every phone browser (and obviously desktop) supporting webgl and webrtc (so basically every Android phone and iPhones above iOS 11)
  • Simplicity, it is a wrapper of different frameworks that makes web AR developing very easy. It is built on top of a-frame and three.js.

So we don’t need Hololens, Cardboard or expensive phones; we just have to reach an AR.js webapp and then we can experience AR.

How is that possible? Well, it turns out AR.js works with markers (not always, but if we wanna be cross-browser, we have to use markers).

A default marker containing a qr-code on the left and AR.js magic on the right — image from this Jerome Etienne’s story.


Markers are a sort of simplified qr-codes. On AR.js we define specific 3D scenes for specific markers, so when the camera recognizes a marker, the web-app shows the 3D model on top of it. Also, markers may contain qr-codes.

An important feature of AR.js is the possibility to use custom markers, the default type is ‘pattern’. I did some research on pattern markers’ limitations, on their size and shape. I learned that:

  • The maximum resolution of a marker is 16x16 pixels
  • They must be square in shape
  • They cannot have white/transparent areas, only light grey (e.g. #F0F0F0)
  • They cannot contain colors, only black and light grey
  • They have to contain simple text, like one letter, a number, or a symbol.

You may use this online tool to generate your custom markers. If you analyze the “.patt” output file, you will find out that the given image is described with a set of characters. So, for good results, it’s better to use dissimilar images for different markers, avoid too complex images or images containing words.

Another important aspect to remember is to have an high contrast between the ‘background’ of the marker and the surrounding environment; for example, if the marker has light grey symbols on black background, the camera will have difficulties on recognize the marker if it is printed and placed on a black desk or displayed on a black screen.

Markers can also be barcodes. They represent a number as a symbol, created with calculus on a matrix. It is suggested to generate markers based on a matrix with an high “hamming distance” (see this table), so the camera can recognize them better. A matrix defines also the maximum number of possible markers (for example the “AR_MATRIX_CODE_3x3_PARITY65” matrix can generate 32 different barcode markers).

Keep in mind that it is better to avoid, if possible, white/transparent color in barcode markers too (this is not confirmed on barcode markers but it is based on empirics).

This is the online generator of barcode markers I used for the following example.

I am showing you some basic code from AR.js documentation and blog, and also a few workarounds, since currently there are some open issues regarding custom markers.

In this simple HTML, we:

  • Import libraries
  • Tell AR.js to recognize barcode patterns that are generated with a 3x3 matrix (line 14)
  • Define two <a-marker> tags, each one identified by two different barcode values (20 and 24)
  • Define a static camera entity (line 32).

To avoid problems, please use specific tags and attributes as shown above. At the time of this writing (April 2019) this example works and it’s based on the newest release of AR.js (version 1.6.2). It is also required to use remote urls for pattern resources, instead of relative urls. Be aware that for security constraints of browsers, your server has to serve this resources through https.

If you want to use custom markers instead of barcode markers, you can generate them with the previously linked tool, and instead of using

<a-marker type="barcode" value="6" (...)

you can use

<a-marker type="pattern" preset="custom" url="...." (...)

where “url” is the remote absolute URL of your “.patt “ file, located remotely somehwere (for instance, in the same repository of the HTML file).

To simplify the detection of markers by the camera, it’s useful to keep in mind some simple rules for create barcode/pattern markers.

For example, the patterns generated for ‘blue’ image and ‘red’ image are very similar (you can check them on the following images); this will make detection very hard.

“Red” marker on the left and the correspondent pattern used by AR.js on the right.
“Blue” marker on the left and the correspondent pattern used by AR.js on the right.

If the image is very complex, the detection may fail too, because the output will look like a set of random characters. From my little experience in playing with markers, I found out that barcode markers are recognizable as much as pattern markers. With the latter it is possible to have more customization, but it is also easier to create a set of similar markers that can confuse the camera, or fall into using complex images as markers.

I answer “absolutely”. Its simplicity is stunning. An approach based on markers is not a real limitation, but rather a paradigm that suits well for an incredible range of use cases. Markers can be showed on mobile and desktop displays or printed and hanged up on walls or boards.

Screenshot taken from my AR.js demo app, while the marker is shown on another display. The yellow 3D box pops up when the camera recognizes the correspondent pattern.

As AR.js shows us, it’s not necessary to have another device over a mobile phone to experience AR, nor to download a third party app (that a common user will surely uninstall soon after, or that probably they won’t download at all). Delivering augmented reality on the web, and make it easily suitable for everyone (literally!) is the key to make this technology pervasive.

A very special thanks to xho for reviewing this article, it wasn’t really readable before him :)

Chialab is a design company. By developing strategy, design, software and content, we generate exciting relationships between brands and people.

The Startup

Medium's largest active publication, followed by +525K people. Follow to join our community.

Nicolò Carpignoli

Written by

Web Software Engineer // Maintainer of AR.js // Working @

The Startup

Medium's largest active publication, followed by +525K people. Follow to join our community.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade