Где браузерные игры хранят сохранения без сервера?
Браузерная игра хранит сохранения в localStorage и IndexedDB — на устройстве игрока, в одном браузере. Разбираем квоты, удаление данных и грабли движков.
Браузерная игра хранит данные внутри самого браузера. Почти каждая веб-игра держится на двух механизмах: localStorage — небольшое хранилище пар ключ-значение на сайт — и IndexedDB, куда более крупная база данных, которой управляет браузер на устройстве игрока. Сервер не получает ничего. Сохранение переживает перезапуски и работает офлайн, но принадлежит одному браузеру на одной машине, и браузер оставляет за собой право его удалить. Всё остальное в статье — следствия этих трёх свойств: где данные физически лежат, сколько влезает и что заставляет их исчезнуть.
Тема постоянно всплывает в читках сообществ, которые мы проводим, и в двух видах. Игроки спрашивают, как игра во вкладке вообще что-то помнит между сессиями. Разработчики — куда уходят сохранения, если они не написали ни строчки кода хранилища, и почему сохранение, работавшее во вторник, к пятнице исчезает. Когда в этом месяце однофайловое демо-приложение, держащее все данные в SQLite, собрало сотни голосов на Hacker News, обсуждение под ним было ровно об этом: сколько веб-страница может надёжно помнить без бэкенда. Честная оговорка сразу: этот блог принадлежит Egmatic, no-code-редактору двухмерных игр в пре-альфе, и при чём тут сохранения — ближе к концу.
Короткий ответ
| Ваш вопрос | Если коротко |
|---|---|
| Где сохранение физически живёт? | На устройстве игрока, в хранилище, которое браузер выделяет каждому сайту |
| Какой механизм использует веб-игра? | localStorage для нескольких мегабайт настроек; IndexedDB для всего, что крупнее |
| Сохранение переживает перезапуск? | Да, пока игрок не очистит данные сайта или браузер их не выселит |
| Сохранение следует за игроком на другое устройство? | Нет. Один профиль браузера на одной машине — и всё |
| Какой риск самый незаметный? | Safari удаляет доступное скриптам хранилище сайта после семи дней без взаимодействия с ним |
Если вы здесь из-за пропавшего сохранения: оно всё ещё на машине, в том профиле браузера, где появилось, — если только данные сайта не чистили и игра не запускалась в приватном окне. Если вы делаете веб-игру или играбельное демо: ниже вся карта территории — от квот по браузерам до того, как Godot, Unity и Construct подключают свои системы сохранений к хранилищам браузера, и до плана, который убережёт от этих сюрпризов на неделе запуска. Хостинг самой сборки — отдельный вопрос, разобранный в статье о том, как разместить веб-демо игры.
Хранилище, которое браузер даёт каждой странице
Браузер выделяет каждому сайту отдельное приватное хранилище, привязанное к origin — источнику страницы, комбинации протокола и домена, с которой она загружена. Из этого следуют два факта. Одна и та же игра, отданная с двух разных адресов, получает два разных хранилища сохранений. И хранилище игры невидимо для всех остальных сайтов — поэтому одна страница не может прочитать сохранения другой.
Внутри этого хранилища важны три механизма.
localStorage — простое хранилище строковых ключей и значений. Оно синхронное: чтение и запись завершаются до следующей строки кода, что удобно — и чем легко злоупотребить: крупная запись в главном потоке подвешивает игру. Места — несколько мегабайт на сайт. Для настроек, разблокировок, лучшего результата или компактного блока сохранения этого хватает, и веб-игры используют его именно так со времён стандартизации.
sessionStorage — тот же интерфейс с короткой жизнью: всё, что в нём лежит, выбрасывается при закрытии вкладки. Игры изредка держат в нём незавершённый прогон, но сохранения живут не здесь.
IndexedDB — настоящая база данных: асинхронная, с индексами, умеющая держать структурированные записи и бинарные блобы, и ей достаётся куда большая доля устройства, чем localStorage. Сюда движки складывают файловые системы, и сюда попадает каждое сохранение тяжелее настроек. Асинхронность означает, что запись не блокирует кадр, — ценой танца с колбэками, который каждый движок уже давно завернул за вас.
Четвёртый термин, который встретится в документации движков, — cookies. Куки — не место, где живут современные сохранения, но они всплывают в их диагностике: настройки браузера, от которых зависит доступность IndexedDB, живут среди настроек кук. Это прямо отмечает документация Godot.
Сколько влезает: квоты по браузерам
Квоты IndexedDB велики и у каждого браузера свои. Опорные числа — из документации web.dev:
| Браузер | Квота IndexedDB | Примечания |
|---|---|---|
| Chrome и Chromium | origin может использовать до 60% всего диска | Сам браузер ограничен 80%; инкогнито-окна с очисткой при закрытии получают примерно 300 МБ |
| Firefox | Браузер может занять до 50% свободного места диска | Группа сайтов (домен вместе с поддоменами) ограничена примерно 2 ГБ |
| Safari | На практике около 1 ГБ | Официально опубликованной квоты нет; игроку показывают запросы шагами по 200 МБ при приближении к лимиту |
localStorage в любом браузере — маленький сосед: единицы мегабайт на сайт и только строки. Для сохранения в виде JSON-блока состояния этого обычно хватает. Для скриншотов, реплеев, наборов уровней или многолетней истории инкременталки — нет, и правильный ответ здесь — IndexedDB с самого начала, а не localStorage плюс хак со сжатием.
Код может спросить у браузера, сколько места осталось: интерфейс StorageManager даёт оценку использования и квоты. Это оценки, а не обещания — в целом точное описание браузерных хранилищ.
Когда браузер выбрасывает сохранения
Хранилище браузера по умолчанию best-effort: браузер старается удержать данные, но не обещает этого, и при нехватке места на устройстве может удалить данные сайта. Документированный порядок выселения в Chromium безжалостен: первым уходит origin, не использовавшийся дольше всех, за ним следующий — пока давление не спадёт. Игрок, не открывавший вашу игру месяцами, по этому правилу — первый кандидат на выселение.
Четыре режима отказа объясняют большинство потерянных сохранений:
- Очистка данных сайта. Кнопка удаления cookies и данных сайта сносит localStorage и IndexedDB разом. Игроки с чистильщиками сталкиваются с этим регулярно.
- Приватные окна. Инкогнито и приватный режим выбрасывают всё хранилище при закрытии окна. Документация Godot говорит прямо: приватный просмотр отменяет персистентность.
- Выселение хранилища. Нехватка места плюс статус best-effort — и данные удалены, хотя никто не решал их удалять. Сайт может запросить постоянное хранилище: persist() просит браузер сохранить данные сайта и чистить best-effort-сайты первыми. Если ваш движок или шаблон выставляет этот переключатель, а в игре настоящие сохранения — включите.
- Семидневный лимит Safari. Safari удаляет всё доступное скриптам хранилище сайта, включая IndexedDB и localStorage, после семи дней пользования Safari без взаимодействия с этим сайтом. Исключение — веб-приложения, добавленные на домашний экран: они живут в собственном отдельном хранилище. Игре, в которую играют еженедельно, лимит не грозит. Игре, в которую собирались вернуться, сохранения к моменту возврата уже нет.
Ни один из них — не баг. Это условия бесплатного хранилища, которое даёт браузер, и причина, по которой игры с серьёзным прогрессом рано или поздно добавляют аккаунты и облачную синхронизацию.
Где сохранения живут у Godot, Unity и Construct
Экспортёры движков переносят свои родные механизмы сохранений в хранилища браузера, поэтому те же правила действуют уровнем выше:
| Движок | Куда попадают сохранения в вебе | На что смотреть |
|---|---|---|
| Godot | Файловая система user:// персистится через IndexedDB | Для персистентности нужны разрешённые cookies, именно IndexedDB; игре в iframe нужны ещё и third-party cookies; приватные окна блокируют персистентность |
| Unity | PlayerPrefs хранятся через IndexedDB, до 1 МБ на веб-сборках | Файловые сохранения из персистентного пути данных игрока попадают в хранилище браузера — внутри тех же квот и правил выселения |
| Construct 3 | Плагин Local Storage держит все данные во внутренней базе браузера — файлов на диске не найти | Несмотря на имя, это полноценная асинхронная система хранения; для продвинутых случаев есть IndexedDB |
| Чистый JavaScript и фреймворки | То, что вызовет код: localStorage для мелких значений, IndexedDB для остального | Все квоты и правила выселения из этой статьи применяются напрямую, без посредников |
Из строки Godot следуют два практических вывода. Персистентность держится на настройках cookies, поэтому игрок, полностью заблокировавший куки, будет играть в веб-сборку без сохранений — обычно не догадываясь, почему. А поскольку порталы встраивают игры в iframe на собственном домене, оговорка про iframe там — нормальный случай, а не экзотика.
Порталы: сохранения живут на их домене
Хранилище привязано к origin, с которого загрузили игру. На портале этот origin принадлежит порталу. Три следствия:
- Сохранение цепляется к домену портала, а не к вам и не к аккаунту игрока на вашем сайте. Игрок, который позже найдёт ту же сборку на вашей странице, начнёт с нуля.
- Все игры, которые портал раздаёт по этой схеме, делят общее хранилище портала — ещё одна причина давать ключам характерный префикс, а не безликий
save. - Правила iframe бьют сюда первыми: у игрока портала с заблокированными third-party cookies персистентность может пропасть целиком — см. таблицу движков выше.
Это не делает порталы плохим выбором хостинга — просто контекст персистентности у них другой. Тестируйте систему сохранений внутри встраивания портала, а не только в локальном экспорте: это два разных мира хранилищ.
SQLite в браузере: паттерн для тяжёлых данных
Когда данным игры становится тесно в хранилище ключ-значение, есть вариант поновее. SQLite компилируется в WebAssembly и может держать целую базу в OPFS — Origin Private File System, приватной области хранилища браузера, привязанной к origin и созданной ровно для этого. Паттерн определяет одно ограничение: приватная файловая система доступна только в воркерах, фоновых потоках, а не в главном потоке — работа с базой уходит из кадрового цикла, где ей и место.
Широкую аудиторию паттерн собрал в этом месяце: Capsule, инструмент для однофайловых веб-приложений, которые держат данные в SQLite, набрал на Hacker News около 380 голосов. Привлекательность проста: полноценная реляционная база поверх мегабайтов состояния — с запросами, с экспортом одним файлом, и всё ещё внутри origin-правил браузера. Для насыщенной сохранениями веб-инкременталки или RPG это текущий потолок персистентности без бэкенда.
У потолка тот же весовой лимит. SQLite в браузере живёт в origin-хранилище: квоты, выселение, семидневный лимит Safari и кнопка очистки данных применяются ровно так же. Более мощный движок для данных не меняет условий земли, на которой стоит.
План сохранений, который переживёт релиз
- Держите сохранение компактным и версионируйте его. Номер версии схемы в блоке сохранения стоит одного поля, а спасает весь конвейер обновлений. Что хранить и когда — отдельный дизайн-вопрос, у него есть своё руководство по системе сохранений.
- Ставьте ключам хранилища префикс с именем игры. На любом общем origin — а их больше, чем кажется, — безликие ключи конфликтуют.
- Добавьте экспорт и импорт файла сохранения. Одна кнопка, скачивающая JSON, спасает во всех режимах отказа выше: игрок, потерявший сохранение от выселения или лимита Safari, восстановит его из файла, а поддержка превращается из расследования в одно предложение.
- Тестируйте в приватном окне и после очистки данных сайта. Это два состояния, в которых ваши игроки реально оказываются, когда что-то ломается, — и оба воспроизводятся по требованию.
- Запрашивайте постоянное хранилище, если сохранения важны. Движок выставляет настройку — включите её; код ваш — один вызов просит браузер вывести игру из-под best-effort-выселения.
- Читайте спрос на кроссплатформенный прогресс как сигнал. Когда игроки просят прогресс с телефона на десктоп, одним браузером тут уже не обойтись. Это момент для аккаунтов и облачных сохранений — есть способ добавить облачные сохранения без сервера. В том же origin-хранилище живут и рекорды, которые веб-демо обычно делают первыми: лидерборд без сервера закрывает ту половину задачи.
Частые ошибки
- Мегабайты в localStorage. Запись падает при упоре в квоту, и до разработчика это доходит репортом игрока, а не сообщением об ошибке.
- Предположение, что сохранение следует за игроком. Другой браузер, другое устройство, другая машина — с точки зрения хранилища это другой человек.
- Тесты только в Chrome. У Safari и самый жёсткий лимит, и меньше всего официальной документации — именно там сохранения реально умирают.
- Долгий прогресс, доверенный порталу. Правила iframe действуют там первыми, и у игрока нет отношений с origin, который держит данные.
- Выпуск сохранения без поля версии. Приходит обновление, старые сохранения парсятся наполовину, а баг-репорты описывают симптомы на три шага в стороне от причины.
- Расчёт на персистентность инкогнито-прогонов. Приватные окна популярны для вторых прохождений веб-игр — и всё в них временно по замыслу.
Место Egmatic
Всё, что выше, — сантехника. Различать IndexedDB и localStorage полезно для веб-разработчика, но это не делает игру лучше спроектированной. Решение, которое заслуживает вашего внимания, — что игра помнит и для кого, а остальное — слой, который должен нести инструмент.
Egmatic — no-code-редактор и движок двухмерных игр в пре-альфе, построенный вокруг слоя выпуска, который относится к персистентности как к части публикации: тот же конвейер, что ведёт игру от сцены до размещённой ссылки, проектируется так, чтобы вести и её сохранения — от локального хранилища до аккаунтов и облачной синхронизации. Тогда вопрос о том, где живут сохранения, становится настройкой, а не исследовательской статьёй. Вы решаете, что игра помнит, редактор исполняет, и каждый файл остаётся вашим.
О стадии скажем прямо: Egmatic в пре-альфе, и мы не называем сроков, которых не можем сдержать. Лист ожидания на egmatic.com — место, где слой персистентности обретает форму: рассказ там о том, что ваша веб-игра должна запоминать, — это вход, который направляет разработку.
Источники
- web.dev — Storage for the web: Chrome разрешает origin использовать до 60% всего диска при потолке браузера 80%; инкогнито-окна с очисткой при закрытии ограничены примерно 300 МБ; Firefox — до 50% свободного места диска, группа сайтов eTLD+1 (домен с поддоменами) ограничена примерно 2 ГБ; Safari — около 1 ГБ с запросами шагами по 200 МБ; best-effort как режим по умолчанию; Chromium первым вычищает origin, не использовавшийся дольше всех; постоянное хранилище как отказ от best-effort; Cache Storage рекомендован для сетевых ресурсов, а не пользовательских данных
- WebKit Blog — Full Third-Party Cookie Blocking and More: семидневный лимит на всё хранилище, доступное скриптам, — IndexedDB, LocalStorage, SessionStorage и регистрации Service Worker в списке типов; применяется после семи дней пользования Safari без взаимодействия с сайтом; веб-приложения, добавленные на домашний экран, держат отдельное собственное хранилище
- MDN Web Docs — Web Storage API: localStorage и sessionStorage хранят строки в рамках origin; оба API синхронные
- MDN Web Docs — Storage API: интерфейс StorageManager даёт оценки хранилища; постоянные бакеты удерживаются до последнего, best-effort чистятся первыми при нехватке места
- Документация Godot Engine — Exporting for the Web: персистентность файловой системы user:// требует разрешённых cookies, конкретно IndexedDB; игре в iframe дополнительно нужны third-party cookies; инкогнито и приватный просмотр блокируют персистентность
- Unity Script Reference — PlayerPrefs: веб-сборки хранят до 1 МБ данных PlayerPrefs через IndexedDB браузера
- Construct 3 Manual — Local Storage plugin (прочитано через снапшот archive.org от 7 марта 2026 — живая страница собирается скриптами): все данные хранятся во внутренней базе браузера, файлов на диске не найти; IndexedDB — для более сложных случаев
- Документация SQLite — Persistence for the sqlite3 WASM/JS build: Origin Private File System как API браузерного персистентного хранилища для баз SQLite; OPFS доступен в контексте воркера, а не главного потока
- Hacker News — Show HN: Capsule, single-file web apps that save their data into SQLite: около 380 голосов, прочитано 25 сентября 2026; обсуждение сообществом веб-приложений, которые держат структурированные данные без бэкенда
Похожие статьи
MonoGame для инди: актуален ли фреймворк в 2026?
Да, MonoGame актуален в 2026 для инди, кому нужен бесплатный C#-фреймворк с чистыми портами. Stardew Valley и Celeste на семействе XNA.
Быстрое прототипирование: соберите игру за несколько часов
Прототип 2D-игры собирают за пару часов, а не за месяцы. Сузьте до одной механики и берите редактор с живым предпросмотром — без шага сборки.
GDevelop против Construct 3: какой редактор выбрать в 2026
GDevelop бесплатен и открыт (MIT); Construct 3 — подписка ($129,99/год Individual, $468,99/место Business). Цены, события, экспорт — сравнение за минуты.