Skip to main content

Umami, Explained: What the Open-Source Analytics Tool Does, and What It Doesn't

· 24 min read
Pere Pages
Software Engineer
Four browser windows on the left send thin teal lines into a small server stack in the centre, which feeds a dashboard on the right with a rising line chart, a bar chart and a world map, next to a small crossed-out cookie icon, on a dark navy background

Umami is a small, open-source tool that counts the visits to your website without cookies and without storing who the visitors are. This post explains how it works, what it measures, how to run it, and where its limits are.

note

Prices, plan limits and features change quickly. Everything here describes Umami as of September 2026 (version 3.4), so check the current terms before you decide. The legal points are my reading of published guidance, not legal advice.

The gist​

Choose Umami when you want simple visit numbers that you own, without a cookie banner. Choose another tool when your analytics must feed advertising or follow single users over months.

  • Run your own copy if you have more than one site. The free Umami Cloud plan covers only one website. Your own copy has no website limit, and ad blockers rarely block it when it runs on your own domain.
  • Use the free Cloud plan for one small site. It covers one website and up to 100,000 pageviews and events a month, and you have no server to update.
  • Read "visitors" as a trend, not as a count of people. Umami recognises a returning visitor without cookies, from a code it calculates, and that code changes every month. So the same person can count more than once.
  • Still update your privacy policy. No cookies means no consent banner, but you must still tell visitors that you measure their visits.

The mental model: a script, a collector and a dashboard​

Umami has three parts, and everything else in this post is a detail of one of them.

  1. A tracking script. A small JavaScript file that you add to every page of your site. When a page loads, it sends a short message to the collector. The message says which page was opened, where the visitor came from, and a few facts about the browser.
  2. A collector. A server that receives those messages. It turns each message into a row in a PostgreSQL database. It also works out whether two messages came from the same visitor, without storing anything in the visitor's browser.
  3. A dashboard. A web app, served by the same server, where you log in and read the numbers: pageviews, visitors, the pages people read, where they came from, and more.

The collector and the dashboard are one application. You can run that application yourself, on your own server. Or you can pay the company behind Umami to run it for you, a service called Umami Cloud. The software is the same in both cases.

With this picture in mind, the rest of the post follows the parts in order: where the software comes from, how the collector counts visitors, what the dashboard shows, how you add the script, and how you run the server.

Where Umami comes from​

Mike Cao started Umami in 2020 because he was frustrated with Google Analytics (GA). The first public release came in September 2020, and version 1.0 followed in October 2020. In 2022, he and his brothers Brian and Francis Cao raised $1.5 million in pre-seed funding (a small first investment) to build a company around it. The same company now sells Umami Cloud.

The code is on GitHub under the MIT licence (named after the Massachusetts Institute of Technology). This is one of the most open licences there is. You can use it, change it and run it for a business, and you don't have to publish your changes. In September 2026 the repository had about 39,000 stars.

Three major versions have changed the software in ways worth knowing:

The most important change for anyone running Umami is in version 3.0: it dropped MySQL. Umami now needs PostgreSQL. If you run an older installation on MySQL, there is an official migration guide. The 2.x line still gets security fixes, but new features only go into 3.x.

The 2026 releases changed what "Umami" means. Version 3.1 added session replay (a recording of what one visitor did on the page), and version 3.2 added heatmaps (a picture of where visitors click and how far they scroll). A few years ago, a common description of Umami was "simple analytics, no replays, no heatmaps". That description is now out of date.

How a visit is counted without cookies​

Umami recognises a returning visitor by calculating an identifier on the server, not by storing one in the browser. This is the single most important fact about it, because it explains both the privacy claims and the limits.

Most analytics tools, such as Google Analytics 4 (GA4), give each browser a random identifier and save it in a cookie. On the next visit, the browser sends the cookie back, and the tool knows it's the same person. Umami never writes to the browser. Instead, when a message arrives, the server calculates a session ID (session identifier) from facts it already has. In the collector's source code, the inputs are:

  • The website's ID — a unique identifier (a UUID, universally unique identifier) that Umami gives each site you add.
  • The visitor's IP address (Internet Protocol address — the network address the request came from).
  • The user agent — a line of text every browser sends that names the browser, its version and the operating system.
  • A salt — a value that changes on a fixed schedule. By default it changes once a month. You can change that with the SALT_ROTATION setting, to day, week or month (environment variables).

The server mixes these inputs with a secret that only the server knows, and passes the result through a hash function. A hash function turns any input into a fixed-length value, and you cannot work backwards from that value to the input. The result is the session ID. The IP address is used for this calculation and to look up the visitor's country and city, and then it's thrown away. The database schema has no column for it.

Umami then groups the events of one session into visits. A visit ends after 30 minutes without activity, so one visitor can have several visits in a month.

What ends up in the database is short. For each session, Umami stores the browser, operating system, device type, screen size, language, and the country, region and city. For each event, it stores the page path and the query string (the part of the address after ?), the page title, the referrer (the page the visitor came from), the campaign tags in the address (the UTM parameters, from Urchin Tracking Module, such as utm_source), the event name, and the hostname.

Two consequences follow directly from this design, and you should keep them in mind whenever you read an Umami number.

  • "Visitors" means "different session IDs", not "different people". The same person counts again after the salt changes at the start of the month, after they move to a new network, after their browser updates, and on each of their devices. And two people behind the same office network, using the same browser version, can be counted as one.
  • Two sites can't be joined. The website ID is one of the inputs, so the same person on two of your sites gets two unrelated session IDs. This is what makes the data hard to misuse, and it's also why Umami can't tell you that "people who read site A also visit site B".

If you do need to follow a person, for example a user who is logged in to your app, Umami has a separate function for it, umami.identify(). You have to call it on purpose. Nothing is followed by default.

What the dashboard shows​

The dashboard starts with the numbers most sites need, and then adds deeper reports.

The main page of each website shows pageviews, visitors, visits, bounce rate and visit duration over a date range you choose. Bounce rate is the share of visits that see only one page. Next to these totals are lists of the top pages, referrers, browsers, operating systems, devices, countries and cities. A realtime view shows the activity of the last few minutes.

Events are anything you want to count that isn't a pageview: a button click, a form sent, a file downloaded. Each event can carry event data, a small set of properties such as { plan: "pro" }, so you can split the count by property later.

On top of those two sources, Umami has a set of reports. The pricing page lists the same reports for every plan, including the free one:

ReportThe question it answers
BreakdownHow do the numbers split by two or more properties at once?
FunnelOf the people who did step 1, how many did step 2, then step 3?
RetentionOf the people who came in one week, how many came back later?
JourneyWhich paths do visitors take through the site?
GoalsHow often is a target page viewed or a target event sent?
UTMWhich campaigns, sources and media bring visitors?
AttributionWhich source should get credit for a conversion?
RevenueHow much money do events with a revenue value add up to?

Some newer features are worth knowing by name:

  • Segments and cohorts (v3.0) — saved filters, and groups of visitors defined by when they first came.
  • Links and Pixels (v3.0) — tracked short links, and an invisible image that counts views in places where JavaScript can't run, such as an email.
  • Boards (v3.1) — custom dashboards that you build from charts.
  • Web Vitals (v3.1) — Google's page-speed measurements, collected from real visitors.
  • Session replay (v3.1) and heatmaps (v3.2) — built on rrweb, an open-source library that records changes to the page. On Umami Cloud, both are only on the Business plan.
  • Teams and share links — Teams let several people see the same websites. A share link makes one website's dashboard public and read-only.

Adding the script to a site​

The minimum setup is one line in the <head> of every page. The script is small: about 2.3 kB when compressed with gzip, as served by Umami Cloud.

<script defer src="https://analytics.example.com/script.js" data-website-id="YOUR-WEBSITE-ID"></script>

With only this line, Umami records a pageview on every page load. It also records a pageview when a single-page application (SPA) changes the address without a full page load, so React, Vue or Astro sites need no extra code.

Settings on the script tag​

You configure the script with data- attributes on the same tag. The tracker configuration docs list them all. The useful ones are:

AttributeWhat it does
data-website-idRequired. Tells the server which website the data belongs to.
data-host-urlSends the data to a different server than the one that served the script.
data-domainsOnly tracks on the listed hostnames, so a local copy of the site isn't counted.
data-auto-track="false"Turns off automatic pageviews, so you send everything yourself.
data-exclude-search / data-exclude-hashRemoves the query string or the # part from the recorded address.
data-do-not-trackRespects the browser's "Do Not Track" setting.
data-tagAdds a label to all events, useful to compare two versions of a page.
data-before-sendNames a function that can change or drop each message before it's sent.

A visitor can also switch tracking off for their own browser. If the browser's localStorage has an item called umami.disabled, the script sends nothing. This is the only contact the script has with browser storage, and it's a read, never a write.

Sending events​

There are two ways to send an event. The first needs no JavaScript: you add attributes to the element, and Umami sends the event when someone clicks it (track events docs).

<button data-umami-event="signup-click" data-umami-event-plan="pro">Sign up</button>

The second is the JavaScript function umami.track(), for cases an attribute can't cover, such as a form that was sent successfully (tracker functions docs):

umami.track('signup', { plan: 'pro', seats: 3 });

Event data has limits: text values up to 500 characters, numbers up to four decimal places, and up to 50 properties per object.

Following a logged-in user​

umami.identify() attaches your own ID to the current session, and optionally some data about it:

umami.identify('user-4821', { plan: 'pro' });

This is the opposite of the cookieless default, so use it with care. Once you send your own user ID, the data is about an identifiable person, and your privacy policy has to say so.

Sending data from a server​

The collector also accepts data from your own backend. You send a POST request to /api/send (no login needed, but it must carry a real user agent), or you use the official Node.js client, @umami/node (sending stats docs). This is useful for events that never happen in a browser, such as a payment confirmed by a webhook (a message that one server sends to another when something happens). For reading data, the same server has a full REST API (an application programming interface, or API, that follows the Representational State Transfer style over HTTP, the HyperText Transfer Protocol), authenticated with an API key.

Running it: self-hosted or Umami Cloud​

You have two ways to get the server: run it yourself for free, or rent it from the company.

Self-hosting​

Umami is a Next.js application that stores its data in PostgreSQL. The install guide asks for Node.js and PostgreSQL 12.14 or newer. The first login is admin with the password umami, and you should change it straight away. There are three common ways to run it:

  • Docker. The repository ships a docker-compose.yml that starts Umami and PostgreSQL together. This is the quickest way on your own server.
  • A hosting platform. The docs have hosting guides for Vercel, Railway, Netlify, Fly.io, DigitalOcean and more, usually combined with a hosted PostgreSQL service such as Neon or Supabase.
  • From source. Clone, install, build and start, like any Node.js app.

For large sites, Umami can also store events in ClickHouse, a database built for analytics queries over billions of rows. It's optional, and most sites never need it.

Self-hosting has two jobs that don't go away. The first is updates: new versions arrive every few weeks, and each update can include a database migration. The second is storage: a self-hosted Umami keeps all data forever unless you delete it (FAQ). The database only grows, so check its size once in a while.

I run my own copy on Vercel with a free Neon database, for seventeen sites. The full setup and its costs are in a separate post.

Umami Cloud​

Umami Cloud runs the same software for you, on servers in the United States (US) or the European Union (EU). The pricing page lists four plans. An "event" means one pageview or one custom event, and each stored event-data property also counts as one event.

PlanPrice per monthEvents per monthWebsitesData kept for
Hobby$0100,00016 months
Pro$201 million, then $0.00003 each202 years
Business$20010 million, then $0.00002 eachUnlimited5 years
EnterpriseCustomCustomUnlimitedCustom

The Hobby plan has no API access. Pro adds the API, access through MCP (the Model Context Protocol, which lets AI assistants read your data), and data import. Business adds session replay, heatmaps and removal of the Umami branding. Import only accepts data from a self-hosted Umami or a CSV (comma-separated values) file, and Umami staff run it for you. There is no import from Google Analytics.

Which one to choose​

The choice mostly comes down to how many sites you have and how much server work you accept.
Self-hostedUmami Cloud
MoneyFree software, you pay for hostingFree for 1 site, then from $20
Number of websitesUnlimited1 / 20 / unlimited, by plan
How long data is keptYou decide6 months to 5 years, by plan
Updates and backupsYour jobDone for you
Blocked by ad blockersRarely, on your own domainOften, on umami.is
Replay and heatmapsIncludedBusiness plan only

Best Good Depends Weakest

Privacy and the law​

Umami's privacy claim is strong, and it is mostly true, but "no cookie banner" does not mean "nothing to do".

The company says Umami is "fully GDPR and CCPA compliant", that it "does not use cookies", and that "you can use Umami without needing to display a cookie consent banner" (pricing FAQ). GDPR is the General Data Protection Regulation, the European Union's main data-protection law. CCPA is the California Consumer Privacy Act.

The cookie part is the one that matters most in Europe. The rule behind cookie banners is the ePrivacy Directive, and it's triggered when a site stores or reads something on the visitor's device. It doesn't matter whether the data is anonymous. Umami never stores anything in the browser, so it doesn't trigger that rule. It only reads the umami.disabled item, and that item exists only when the visitor sets it to opt out.

Two things still remain your job:

  1. Tell people. Your privacy policy has to say that you measure visits, with which tool, and where the data is stored. A policy that says "we use no tracking" becomes false the day you add the script.
  2. Don't undo the design. umami.identify() with a real user ID, or event data that contains an email address, turns anonymous counts into personal data. Then the full weight of the GDPR applies.

The Spanish data protection authority's rules for when analytics needs consent, and the paperwork a cookieless tool still leaves you, are covered in detail in the post about my own setup.

The limits​

Umami is honest about what it is, but some limits only show up after you install it.

Ad blockers block Umami Cloud. EasyPrivacy, the most common tracker blocklist, contains the rule ||umami.is^$third-party (the list itself). Every visitor with uBlock Origin, Brave or a similar blocker is invisible to a site that loads the script from Umami Cloud. EasyPrivacy also has rules for any umami.* domain that serves /script.js, and for any file called umami.js. A self-hosted server on a subdomain of your own, such as analytics.example.com, matches none of these rules. You can also rename the script and the collection address with two settings, TRACKER_SCRIPT_NAME and COLLECT_API_ENDPOINT, which the docs describe for exactly this purpose. Developer audiences block the most, so this matters most for technical sites.

The visitor count is an estimate. The monthly salt, changing networks and several devices all make one person count more than once. The trend over time is reliable. The absolute number of "unique visitors" is not a count of people.

Data about a single visitor is thin on purpose. You can't see the journey of one anonymous person across months, because their session ID changes. Session replay shows single sessions, but only inside that short period.

No advertising features. Umami doesn't connect to Google Ads or Meta, can't build audiences for ads, and doesn't model which ad deserves credit across devices. It does store the click IDs that ad platforms add to links (such as gclid), but it doesn't talk to those platforms.

No import from Google Analytics. If you switch, your history stays in the old tool. Keep both running for a few months if you want to compare them.

Self-hosted storage grows forever. Nothing is deleted automatically, so plan a yearly check of the database size.

How it compares to the other tools​

Umami belongs to a group of privacy-friendly analytics tools. They differ mostly in licence, price and how deep the analysis goes. The table uses the vendors' own claims, linked below it.

The table names some licences, and they need a short explanation. AGPL is the GNU Affero General Public License: if you change the software and offer it to others over a network, you must publish your changes. GPL is the GNU General Public License, with the same rule for software you distribute. EUPL is the European Union Public Licence. For simply running the tool on your own server, all of them are free to use.

ToolCookies by defaultCan you host it yourself?Free hosted planMain focus
UmamiNoneYes, MIT1 site, 100,000 eventsSimple web analytics, growing into product analytics
PlausibleNoneYes, AGPLNo, from $9Simple web analytics
FathomNoneNoNo, from $15Simple web analytics
RybbitNoneYes, AGPLNo, 7-day trialWeb and product analytics
GoatCounterNoneYes, EUPLYes, for reasonable useVery simple counts
Cloudflare Web AnalyticsNoneNoYesSimple counts, sampled
MatomoYes, can be turned offYes, GPLNoFull Google Analytics replacement
PostHogYes, can be changedYes1 million eventsProduct analytics, replay, experiments
Google Analytics 4Yes, for 2 yearsNoYesMarketing and advertising

Best Good Depends Weakest

Sources: Plausible and its pricing, Fathom pricing, Rybbit and its pricing, GoatCounter, Cloudflare Web Analytics, Matomo and its guide to running without cookies, PostHog pricing and its cookie settings, and Google Analytics cookies.

Umami's closest rival is Plausible. They have almost the same privacy design. Umami has the more open licence, a free hosted plan and more reports, while Plausible has no free plan. The biggest difference is with PostHog and GA4. Those tools follow individual users by default, which gives deeper answers but brings back cookies and consent banners.

When Umami is the right choice​

Umami fits best when you want honest, simple numbers about your own sites and you don't want a consent banner.

It's the wrong choice when the analytics exist to feed advertising, or when the product needs to know what one user did over a long time. For almost everything in between — blogs, documentation, portfolios, small business sites and side projects — it answers the questions you actually ask: did anyone come, from where, to which page, and is the number going up.

References​

  1. umami-software/umami — source code, licence and releases
  2. Umami raises $1.5 million in pre-seed funding — Yahoo Finance
  3. Umami v3.0.0 release notes
  4. Umami collector source, /api/send (v3.4.0)
  5. Umami docs — environment variables
  6. Umami docs — tracker configuration
  7. Umami docs — tracker functions
  8. Umami — pricing and plan limits
  9. Umami docs — FAQ
  10. EasyPrivacy — third-party tracking servers list