Privacy
No accounts, no cookies, and your games stay in your browser. Here's everything the site handles, and where it goes.
Playing a game
When you play on this site, the engine running in your browser tab works out
every move. The position is kept in the part of the address after the #,
and browsers never send that part to a server. When you open a game's page,
the server sees which game you opened, as it would for any page. It never
sees the position or the moves. When a game ends, the page tells the server
which game you played and how it ended, so the site can count it. Counting
visits lists what that carries.
What stays on your device
Your browser keeps a few things for this site. None of them is sent anywhere, apart from the count of a finished game described under Counting visits.
- Every game you finish, for Your results, in IndexedDB.
- The difficulty you last picked, in local storage under
ttt-level. - The game in each tab, so a reload keeps your place, in session storage
under
ttt-game:and the game's name. It's gone when you close the tab. - Your seat in an online room, in session storage under
ttt-room:and the room's code. It's gone when you close the tab too. - The page you're leaving and the one you're going to, in session storage
under
ttt-transition, so the next page knows how to animate in. The next page deletes it as soon as it opens. - The site's pages and code, in the service worker's cache, so you can play offline.
For each game you finish, your browser keeps the name of the game, whether you played the computer, someone at the same screen or someone online, the difficulty against the computer, how it ended, which side you played, how many moves there were, the final position and when it ended. The record itself never leaves your device unless you download it as JSON from Your results.
Light or dark follows your device's setting, so there's nothing stored for it. Clearing this site's data in your browser removes everything above.
Cookies
The site sets no cookies, and nothing it loads sets any either.
What the server logs
The server writes one line for each request: the method, the route it
matched, the status, the size of the response and how long it took. For a
page, the route is the page's own address, like /games/ultimate, so the log
shows which game's page was opened. For a room or an API call, it's the
pattern, like /room/{code} or /api/v1/games/{id}/best, not the address
you asked for. An address that matches no route is logged with its path,
with any room code taken out. A line never carries a query string, a
position, a room code, your IP address or your browser's name. When
something breaks, the server also logs what failed, without any of those.
Nothing else on the server counts or keeps your IP address either.
The log goes to the hosting provider, Railway, and it's kept for as long as Railway keeps logs.
Playing a friend online
A room lives in the server's memory: its code, the game, the position, the score and a token for each seat, and nothing about who opened it. A room is deleted after 10 minutes with nobody sitting down, moving or starting another game in it. Nothing about a room is written to disk, and a restart ends every room.
The room's code is only in its link. The server's log shows /room/{code},
not the code itself.
The API and MCP
There's no account and no key. A call carries a game position, and the server uses it to answer and then drops it. Nothing about the call is kept beyond the log line above.
An MCP call writes a second line: which tool or resource the app asked for, the name and version the app gives for itself, a short tag that tells one session from another, whether the call worked and how long it took. That line carries no position either.
The answers from legal, best and analyze can be cached. An answer from
the table never changes, so it keeps for a year. An answer the computer
searched for keeps for an hour, because a new version of the engine can
answer differently. The CDN in front of the site, your own client, or a
proxy along the way can keep a copy under the address you asked for. That
address holds the position, and nothing about you.
An MCP session keeps a count of its expensive calls in the server's memory, and closes after 10 minutes with no calls.
A board in a chat
When an AI assistant like Claude or ChatGPT opens a board for you, the board runs inside the chat app. Each move goes from the chat app to this site's MCP endpoint as a tool call, and the board tells the assistant where the game stands. The board loads its font from tictactoe.fun and nothing else. What the chat app does with your conversation is up to its own privacy policy.
Counting visits
The site counts page views and finished games with Pirsch, an analytics service that uses no cookies. Every page loads Pirsch's script from this site's own server, and the script reports to this site's own server, which passes the count on. Your browser never talks to Pirsch. Each page view sends:
- the page's address, without its query or anything after the
#, and with every room shortened to/room/ - the page's title
- the address of the page you came from, cleaned the same way
- your screen's width and height
- your IP address, your browser's user agent and language, and the details your browser shares about itself in client hints
When you finish a game, the page sends the same things once more, along with:
- which game you played
- whether you played the computer, someone at the same screen or someone online
- the difficulty, against the computer
- whether you won, lost or drew, or which mark won when two people shared a screen
It never sends the position, the moves or how many there were.
Pirsch uses the IP address and user agent to tell one visit from another without a cookie. Pirsch's privacy policy says it hashes them with a salt that changes every day, and never stores the IP address itself.
When something breaks
When the site's code fails, in your browser or on the server, a short error report goes to GlitchTip, an error tracker that Fresh Codes LLC runs itself. The site sends none while everything works, and a page sends five at most each time you open it.
A report from your browser carries:
- the error's message, with any room code taken out, and with anything
after a
?or#taken out of any address in it - where in the site's own code it happened, and nothing about code from other sites or browser extensions
- the page's address, without its query or anything after the
#, and with every room shortened to/room/ - your browser's name and main version number, like Firefox 130
- the version of the site, and the time
The page's address names the game you're on, like /games/ultimate. A
report never carries your IP address, your browser's full user agent, the
position or moves of your game, a room code or a seat token. The report goes
to this site's own server, which cleans it again and passes it on as its own
request, so GlitchTip never sees your IP address either.
A report from the server carries what failed, the route it happened on,
like /api/v1/games/{id}/legal, and the version of the site. Like the
log, it never carries a query string, a position, a room code or your IP
address.
Who else is involved
- Railway runs the server and keeps its log.
- Cloudflare sits in front of it, passes requests through and caches the answers that can be cached.
- Pirsch counts visits and finished games.
None of them gets anything from this site beyond what this page describes. The site sells nothing about you, and it has no ads.
Your choices
The server keeps nothing about you, so there's nothing on it to look up or delete. To remove what's on your device, clear this site's data in your browser. For anything else, write to the address below.
Changes
If what the site does with data changes, this page changes with it, and the date below moves.
Who runs it
tictactoe.fun is run by Fresh Codes LLC.
Questions go to hello@fresh.codes.
Last updated 2 October 2026.