Open-source project
mathjax/MathJax avatar
mathjax/MathJax

MathJax: TeX, MathML and AsciiMath in the browser without plugins

Beautiful and accessible math in all browsers

10,924 stars1,192 forksJavaScriptApache-2.0

At a glance

What is it?
MathJax is a JavaScript display engine that typesets LaTeX, MathML and AsciiMath in web pages and in Node, with screen reader support built in. This covers how the v4 components load, how to install them, and where the approach costs you.
Who is it for?
Adopt MathJax when your pages already contain TeX or MathML and you need accessible output without asking readers to install anything. Do not adopt it if you need a small bundle and a narrow subset of LaTeX, since the component files and font handling are heavier than a minimal renderer.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 89 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What MathJax solves for page authors and Node services

A page that contains mathematics has to turn notation into something a browser can lay out. MathJax is a JavaScript display engine for LaTeX, MathML and AsciiMath notation that works in modern browsers, and the README states it requires no setup on the part of the user: no plugins to download, no software to install. That constraint is the whole point. The page author includes MathJax and some mathematics, and the reader sees typeset output.

The audience is split. On one side are people publishing documentation, course notes or papers in HTML who already have TeX source and do not want to convert it by hand. On the other are developers embedding math in an application, where the README points to a powerful API for integration with other web applications and to components that can be imported into a Node process rather than a browser. Accessibility is a stated feature, not an afterthought: screen reader support, automatic speech generation, and an expression explorer for investigating typeset mathematics at a more granular level than the complete expression.

If your problem is simply displaying a handful of formulas and you control the markup, this is more machinery than you need. If your problem is that the same notation has to render for sighted readers, for a screen reader, and for a server side pipeline, MathJax is aimed exactly at that.

Components, not source: what actually ships in this repository

The README is explicit that this repository contains only the component files for MathJax, not the source code, which lives in a separate repository. That distinction matters when you file a bug or read the tree. The top level holds files such as tex-chtml.js, tex-svg.js, mml-chtml.js, tex-mml-svg.js and their -nofont variants, plus directories named input, output, adaptors, a11y, sre, ui, and the entry points node-main.mjs, node-main.cjs and node-main.js.

Those file names encode the data flow. A component named tex-chtml combines a TeX input processor with a CHTML output renderer; tex-mml-svg accepts both TeX and MathML input and renders SVG; the -nofont variants are the same pipeline without the bundled web fonts. The README describes components as either complete combinations or as pieces that can be loaded on demand or combined by a configuration that specifies the pieces you want. The loader.js and startup.js files at the top level are the machinery for that: the loader pulls in the modules a configuration asks for, and startup runs the initial typesetting pass.

The package.json confirms the packaging story. The main field points at node-main.mjs, with conditional exports mapping import to that file and require to node-main.cjs. The README notes the components are ES6 format as CommonJS modules. If your build pipeline cannot handle that combination, the component files are not a drop-in for you, and the README does not document a rollback path to the version 2 layout, where the web files and the source files were the same thing.

Installing MathJax from a CDN or hosting your own copy

If you load MathJax from a CDN, the README says there is no need to install anything. You add a script tag and MathJax handles the rest. The example in the README uses the jsDelivr URL for the tex-mml-chtml component, which accepts TeX and MathML input and renders CHTML output.

html
<script src="https://cdn.jsdelivr.net/npm/mathjax@4/tex-mml-chtml.js" defer></script>

The defer attribute means the script is fetched without blocking parsing, and MathJax typesets after the document is ready. After that tag, any TeX or MathML in the page is picked up; you should see the formulas rendered in place of the raw markup.

To host it yourself, the README gives two routes. The npm route installs the packaged mathjax package and moves the directory to a server location:

bash
npm install mathjax@4
mv node_modules/mathjax <path-to-server-location>/mathjax

The git route does the same with a clone, replacing the npm step with git clone https://github.com/mathjax/MathJax.git mathjax and then moving the mathjax directory. Either way, the script tag then points at your own URL rather than a CDN:

html
<script src="<url-to-your-site>/mathjax/tex-chtml.js" defer></script>

Note that the self-hosted example uses tex-chtml.js while the CDN example used tex-mml-chtml.js. The file name is the configuration, so choose the component that matches the input formats you actually accept. The README's hosting documentation is where the full list lives.

Using MathJax components in a Node application

The npm package is not browser-only. The README shows importing it and initializing with a configuration, then calling a conversion promise. In an ES module application:

js
import MathJax from 'mathjax';
await MathJax.init({
  loader: {load: ['input/tex', 'output/svg']}
});
const svg = await MathJax.tex2svgPromise('\\frac{1}{x^2-1}', {display: true});
console.log(MathJax.startup.adaptor.serializeXML(svg));

Here the loader configuration names the input and output modules explicitly rather than picking a prebuilt component, and tex2svgPromise returns a promise for an SVG node that the adaptor serializes to a string. For an ES5 application the README shows the same thing with require and a then chain:

js
const MathJax = require('mathjax');
MathJax.init({
  loader: {load: ['input/tex', 'output/svg']}
}).then(() => {
  const svg = MathJax.tex2svg('\\frac{1}{x^2-1}', {display: true});
  console.log(MathJax.startup.adaptor.serializeXML(svg));
}).catch((err) => console.log(err.message));

The README attaches a warning to both snippets: this technique is for node-based applications only, not for browser applications. It sets up an alternative DOM implementation that you do not need in the browser and depends on node and the local file system in other ways. The README states this setup will not work properly in the browser even if you bundle it with webpack or another bundler. If your goal is client side rendering, use the script tag path instead.

Where MathJax is the wrong tool

The Node path is the clearest boundary. It is not a universal renderer you can run anywhere JavaScript runs. The README's own note says the technique depends on node and the local file system and will not work properly in the browser even after bundling. Teams that assume a single code path can serve both a Node service and a client bundle will have to maintain two setups.

Size is the second boundary, though the README does not quantify it. The repository ships font directories and adaptors alongside the renderers, and the -nofont components exist precisely because the font payload is separable. If you are optimizing a page for a small initial download and your math is limited, a lighter renderer that supports a narrower slice of TeX may be the better trade. MathJax's pitch is coverage across LaTeX, MathML and AsciiMath plus accessibility features, and that coverage is what the extra components buy.

Third, the repository layout can mislead. This repository is the packaged version and the main issue tracker, while development happens in MathJax-src. Someone reading the tree for implementation details will not find them here. And the package.json test script is the literal string echo 'No tests defined', so do not expect a test suite in this repository to tell you whether a change is safe.

MathJax versus KaTeX: two different bets

KaTeX is the comparison most people reach for, and the difference is in the approach rather than in the output quality. KaTeX is a self-contained library that renders a defined subset of LaTeX synchronously, with the goal of speed and a small footprint. MathJax, by the description in this README, is a display engine with a loader and a startup phase, accepting LaTeX, MathML and AsciiMath, and carrying accessibility features such as automatic speech generation and an expression explorer.

That means the choice is about what you accept as input and what you owe your readers. If your source is hand-written LaTeX that stays inside a documented subset, a synchronous renderer fits the page budget. If your source arrives as MathML from a converter, or as AsciiMath from a wiki, or if you need the accessibility layer, MathJax's multi-format input is the reason to take on the loader. The README also notes cut-and-paste interoperability as a feature, which is a different promise from rendering speed.

LaTeX itself is not an alternative in the same sense. The search phrase mathjax vs latex conflates a document preparation system with a browser display engine; MathJax consumes TeX notation, it does not produce PDFs or run packages.

Maintenance, licensing and upgrade cost

The last push to this repository was on 2026-07-03, the same date as the 4.1.3 release, and the repository is not archived. Releases in the 4.1 line have arrived on a rough cadence of a few months apart: 4.1.1 on 2026-02-19, 4.1.2 on 2026-05-03, 4.1.3 on 2026-07-03. The README's own structure explains part of the maintenance cost: the packaged components in this repository are generated from the source in MathJax-src, so component files change when the source does, and pinning a version pins the whole bundle.

Upgrade cost is dominated by the component name, because the file name is the configuration. Moving from a tex-chtml script tag to a tex-mml-chtml one is a source change, not a config flag. The README documents the version 2 to version 3 shift in packaging: in version 2 the web files were also the source files, while in version 3 and above the source files are no longer on the CDN because they are not what runs in the browser. Any project that deep-linked into MathJax v2 internals faces that as a migration, and the README does not document a compatibility shim.

Licensing is Apache-2.0, per the LICENSE file and the license field in package.json. That is a permissive licence with a patent grant and a notice requirement; it is not a copyleft licence, so it does not force you to publish your own source. This is a description of the licence identifier, not legal advice, and the LICENSE file in the repository is the text that governs.

Editorial conclusion

Adopt MathJax when your pages already contain TeX or MathML and you need accessible output without asking readers to install anything. Do not adopt it if you need a small bundle and a narrow subset of LaTeX, since the component files and font handling are heavier than a minimal renderer. Before committing, verify which component name matches your input and output formats in this repository's file list, and confirm whether your build can accept an ES6 CommonJS module. If you are rendering server side, check that your runtime is Node, because the README states the Node setup relies on node and the local file system and will not work properly in the browser.

Frequently asked questions

What is MathJax used for?

It is an open-source JavaScript display engine for LaTeX, MathML and AsciiMath notation that works in modern browsers, so page authors can include mathematics and be confident readers can view it without plugins or extra software. The same components can also be used in a Node application.

Is MathJax similar to LaTeX?

MathJax accepts LaTeX notation as one of its three input formats, alongside MathML and AsciiMath, and displays it in HTML pages. It is not a document preparation system: it renders notation in a browser or a Node process rather than producing a document.

Is MathJax free?

The package.json license field and the LICENSE file both give Apache-2.0, which is a permissive open source licence. The README also notes there is no need to install anything if you load MathJax from a CDN into a web page.

How do I install MathJax?

For a web page loaded from a CDN there is nothing to install: the README shows a single script tag pointing at the jsDelivr URL for a component such as tex-mml-chtml.js. To host it yourself, the README gives npm install mathjax@4 followed by moving node_modules/mathjax to a server location, or cloning the repository instead.

How do I use MathJax in an HTML page?

Include a script tag for the component you need and put the mathematics in the page. The README uses a jsDelivr script tag for tex-mml-chtml.js with the defer attribute, which accepts TeX and MathML input and renders CHTML output.

How do I use MathJax in a Node application?

Install the mathjax package, import or require it, call MathJax.init with a loader configuration such as input/tex and output/svg, then call tex2svgPromise or tex2svg and serialize the result. The README warns that this setup is for node-based applications only and will not work properly in the browser, even with a bundler.

Official sources

  1. License: Apache-2.0
  2. mathjax/MathJax on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/mathjax-mathjax.svg)](https://hysenlabs.com/projects/mathjax-mathjax)