Перейти к содержимому
Забрать бесплатно
Модификации выключены. Так эта страница выглядит на обычной Тильде.

static.tildacdn.com: это CDN Тильды, и домен собирается в браузере

29 июля 2026 12 МИН КОМАНДА MODKOD

`static.tildacdn.com` — домен, с которого Тильда отдаёт свой JavaScript, CSS и картинки: на снятой странице магазина оттуда приезжают 20 файлов из 21. Домен не зашит в код константой — он собирается из строки `https://static.tildacdn.` и зоны, которую рантайм читает из одного атрибута в разметке. Рядом работают ещё семнадцать адресов, у каждого своя задача, а у форм, магазина и доставки — правило: при отказе переключиться на дублёра ровно один раз.

✓ ПРОВЕРЕНО 29 июля 2026 18 адресов Тильды — 16 в 53 файлах рантайма и 2 только в HTML снятой страницы, включая ws.tildacdn.com, к которому не обращается ни один файл; сборка адреса из строки и зоны, включая optim.tildacdn, store.tildaapi, geo.tildaapi и members.tildaapi; 10 файлов, читающих data-tilda-root-zone, и своя копия функции почти в каждом; data-tilda-root-zone="com" на снятой странице; 10 атрибутов data-tilda-* на странице и 4 из них, которых не читает ни один файл рантайма; сторож двух доменов в избранном; условие одноразового переключения на forms2 и на зону 2 у доставки; tilda-fallback-1.0 целиком, включая жёстко зашитый neo.tildacdn.com, повтор каждые 500 мс без предела, таймаут 30 секунд и показ страницы силой через 5 секунд — снятая страница магазина Тильды и 53 файла её рантайма

Короткий ответ

static.tildacdn.com — домен, с которого Тильда отдаёт свой код и картинки. На снятой странице магазина оттуда приезжают 20 файлов из 21 и все изображения. Зону в адресе выбирает атрибут data-tilda-root-zone у тега #allrecords, по умолчанию com. Рядом ещё семнадцать адресов: оптимизатор картинок, формы, магазин, доставка, два геосервиса, кабинет покупателя, спасательный код — и по дублёру у пяти из них.

Домен не константа: его собирает рантайм

В коде нет строки https://static.tildacdn.com. Есть строка без зоны, к которой зона приклеивается:

"https://static.tildacdn." + t_store__getRootZone() + "/js/" + n + ".min.js"

Саму зону даёт одна функция, и она читает одну вещь из разметки:

function t_getRootZone() {
  var t = document.getElementById("allrecords");
  return t && t.getAttribute("data-tilda-root-zone") || "com";
}

Атрибута нет — подставляется com. На снятой странице он есть и равен com.

Атрибут data-tilda-root-zone читают 10 файлов из 53 — это самый востребованный атрибут страницы. Общей функции для этого нет: почти каждый файл несёт свою копию с той же логикой и своим именем.

ФайлИмя функции
tilda-scripts-3.0t_getRootZone
tilda-forms-1.0t_forms__getRootZone
tilda-delivery-1.0t_delivery__getRootZone
tilda-lazyload-1.0t_lazyload__getRootZone
tilda-zero-1.1t396__getRootZone
tilda-wishlist-1.0twishlist__getRootZone
tilda-phone-mask-1.1t_form_phonemask_getRootZone
tilda-cart-1.1, tilda-catalog-1.1без имени, сжато до одной буквы
tilda-buyer-dashboard-1.0читает атрибут прямо в t_bd__init

Есть и обратная операция — для строк, где .com всё-таки зашит:

function t_modifyRootZone(t) {
  return t && t.includes("static.tildacdn.com")
    ? t.replace("static.tildacdn.com", "static.tildacdn." + t_getRootZone())
    : t;
}

То есть зашитые адреса в коде есть, и их правят на ходу подстановкой.

Карта поддоменов

Все найдены в 53 файлах рантайма. В колонке «как собирается» — то, что в коде буквально. Считаю так: варианты одной и той же машины по зоне — одна строка (store.tildaapi.com и store.tildaapi.ru это один адрес), а дублёр — отдельная, потому что у него другое имя.

АдресКак собираетсяЗадача
static.tildacdn.<зона>"https://static.tildacdn." + зонаJS, CSS, картинки
optim.tildacdn.<зона>"optim.tildacdn" + "." + зонауменьшенные копии картинок
static3.tildacdn.comзашит, без зоныподмена картинки при отказе static
thumb.tildacdn.comзашитпревью в lazyload-1.3.min.export.js
neo.tildacdn.comзашит, без зоныспасательный код
ws.tildacdn.comзашит в HTML страницытолько dns-prefetch, см. ниже
forms.tildacdn.comwindow.tildaForm.endpointприём данных форм, брошенные корзины
forms.tildaapi.<зона>"forms.tildaapi." + зонатот же приём, если зона задана
forms2.tildacdn.comзашит, подставляется при отказедублёр приёма форм
store.tildaapi.<зона>"store.tildaapi." + зонатовары, наличие, корзина каталога
store2.tildaapi.<зона>"store2.tildaapi." + зонадублёр магазина при отказе
delivery.tildacdn.com"https://delivery" + endpointDeliveryсписок стран, расчёт доставки
delivery2.tildacdn.comendpointDelivery = "2.tildacdn.com"дублёр доставки при отказе
geoserv.tildacdn.com"https://geoserv" + endpointDeliveryопределение города, подсказки улиц
geoserv2.tildacdn.comтот же endpointDeliveryдублёр геосервиса
geo.tildaapi.<зона>"https://geo.tildaapi." + зонастрана посетителя для маски телефона
members2.tildacdn.comзашит, если зоны неткабинет покупателя
members.tildaapi.<зона>"https://members.tildaapi." + зонатот же кабинет, если зона есть

Отдельно — tildacdn.info: это не адрес, а второй домен верхнего уровня, который избранное принимает наравне с .com.

Два адреса взяты не из кода, а из HTML снятой страницы: neo и ws. И ws интересен тем, что его нет ни в одном из 53 файлов рантайма — в разметке для него стоит <link rel="dns-prefetch">, то есть браузеру велено заранее выяснить адрес машины, к которой на этой странице никто не обращается. static в HTML упомянут 49 раз, optim и store — ни разу: эти адреса появляются только в браузере, когда отработают скрипты.

Два места стоит прочитать внимательно. Кабинет покупателя при наличии зоны уходит не на другой поддомен, а на другой домен — tildaapi, а не tildacdn:

window.tildaMembers.endpoint = "https://members2.tildacdn.com";
var e = document.getElementById("allrecords");
if (e) { var t = e.getAttribute("data-tilda-root-zone");
  t && (window.tildaMembers.endpoint = "https://members." + "tildaapi." + t) }

А избранное принимает адрес картинки только с двух доменов и молча отбрасывает любой другой:

"image" == p[0] && (p[1].indexOf("tildacdn.com") > 0 || p[1].indexOf("tildacdn.info") > 0) && (i = p[1])

Отсюда практический вывод: перенесли картинки товаров на свой домен — в избранном у них пропадут превью, и ошибки в консоли не будет.

Что именно лежит на static

Два вида путей, оба видны в коде и на странице.

Код — /js/<имя>.min.js и /css/<имя>.min.css. Именно так рантайм догружает то, чего на странице изначально нет:

i.src = "https://static.tildacdn." + o + "/js/" + n + ".min.js"
s.href = "https://static.tildacdn." + o + "/css/" + n + ".min.css"

Картинки — путь начинается с /tild и шестнадцатеричных групп: /tild6136-3837-4939-a634-366663326334/. На снятой странице таких путей семь, и все с static.tildacdn.com. Плюс отдельная папка /lib/linea/ — оттуда корзина берёт иконки «плюс», «минус» и «удалить».

Отложенная загрузка переписывает адрес не любой картинки, а только своей:

if (-1 === e.indexOf("static.tildacdn." + t_store__getRootZone())) return e;

Картинка с чужого домена в этот механизм не попадает вообще. А та, что попала, переезжает на домен оптимизатора — прямо в браузере, подменой в пути:

r = /\/static\.tildacdn\.(info|.{1,3})\//
function b(e) { return e.replace(r, function (e, t) {
  return "/" + t_lazyload__getThumbDomainName() + "." + (l[t] || "com") + "/" }) }
function t_lazyload__getThumbDomainName() { return "optim.tildacdn" }

Поэтому optim не найти в исходном коде страницы: в разметке стоит static, а optim появляется в адресе только после того, как отработал скрипт. Обратите внимание и на саму регулярку: рядом с зоной из трёх знаков в ней стоит info — это второй домен верхнего уровня, а не опечатка.

Если картинка с static не загрузилась, адрес меняется ещё раз, уже на зашитый .com:

if (h(t)) return window.lazy_err_static = "y",
  void L(e, t.replace(r, "/static3.tildacdn.com/"));

Формы: один повтор, и больше никогда

Адрес приёма формы лежит в window.tildaForm.endpoint и по умолчанию равен forms.tildacdn.com. При неудаче код пробует дублёра:

if (secondFormTypeXhr && (secondFormTypeXhr.status >= 500 || 408 == secondFormTypeXhr.status
    || 410 == secondFormTypeXhr.status || 429 == secondFormTypeXhr.status
    || "timeout" == secondFormTypeXhr.statusText)
    && -1 !== window.tildaForm.endpoint.indexOf("forms.tilda"))
  return window.tildaForm.endpoint = "forms2.tildacdn.com",
    window.tildaForm.send(form, btnSubmit, formType, formKey), !1;

Условие переключения требует, чтобы в текущем адресе была подстрока forms.tilda. После переключения адрес — forms2.tildacdn.com, и такой подстроки в нём нет: там forms2.tilda. Значит:

  • повтор возможен ровно один раз за жизнь страницы;
  • window.tildaForm.endpoint после переключения остаётся forms2 до перезагрузки — все следующие отправки на этой странице идут туда и повтора уже не получают;
  • список поводов для повтора закрытый: 500 и выше, 408, 410, 429, таймаут. Код 402 или 403 в него не входит и повтора не вызывает.

Оттуда же корзина тянет брошенные заказы, и этот адрес зашит целиком, без зоны:

var e = "https://forms.tildacdn.com/api/v1/getlostbasket/";

Доставка: та же конструкция, тот же один повтор

Доставка держит не имя хоста, а его хвост:

endpointDelivery: ".tildacdn.com",
changeEndpoint: function (t, r, n) {
  var i = this;
  "object" == typeof t && (t.status >= 500 || 408 == t.status || 410 == t.status
    || 429 == t.status || t.isTimeout) && ".tildacdn.com" === i.endpointDelivery
    ? (i.endpointDelivery = "2.tildacdn.com", "function" == typeof r && r())
    : …

Адреса собираются приклеиванием: "https://delivery" + endpointDelivery и "https://geoserv" + endpointDelivery. После переключения хвост становится 2.tildacdn.com, и те же строки дают delivery2.tildacdn.com и geoserv2.tildacdn.com.

Дальше — то же самое, что у форм: сторож ".tildacdn.com" === endpointDelivery после переключения ложен навсегда. Один повтор, и всё. Список поводов совпадает с формами вплоть до кодов.

Если и дублёр не ответил, посетитель ничего не узнаёт — сообщение уходит в консоль, по-английски:

console.error("[" + t.status + "] " + t.responseText + ". Please, try again later.")

Но зону доставка передаёт не в адресе, а внутри запроса. В четырёх местах файла стоит одно и то же:

var v = document.getElementById("allrecords").getAttribute("data-tilda-root-zone");
v && (l.rz = v);

Поэтому endpointDelivery и зашит на .tildacdn.com: адрес у доставки один на все зоны, а зона едет полем rz в теле. Это единственная служба, устроенная так, — у остальных зона попадает в имя хоста.

Магазин: те же адреса, но собранные фабрикой

Каталог держит адрес в window.t_store_endpoint и пересобирает его отдельной функцией:

function t_store__setupEndpoint() {
  var t = t_store__getRootZone();
  window.t_store_endpoint = "store.tildaapi." + t;
}

До первого вызова там лежит зашитое store.tildaapi.com. А в корзине то же имя собирает фабрика из двух частей, и вторая часть — выбор домена:

TCartServerLocation = { CDN: "tildacdn", API: "tildaapi" };
function t_cart__getServerName(t)  { return "store."  + t + "." + getRootZone() }
function t_cart__getServer2Name(t) { return "store2." + t + "." + getRootZone() }

То есть фабрика умеет собрать и store.tildacdn.<зона>. Но все шесть мест, где её вызывают, передают TCartServerLocation.API — член CDN объявлен и не используется ни разу. В таблицу я его не внёс именно поэтому: адрес, который никто не запрашивает, — не адрес.

Разница с формами и доставкой в том, что магазин зону перечитывает: дублёр получается store2.tildaapi.<зона>, а не зашитый .com. У форм наоборот — переключение ведёт на forms2.tildacdn.com независимо от зоны. Подробнее, с замером числа запросов на каждый код ответа, — в разборе ошибок 402, 403 и 429.

Если домен недоступен

Первым на странице стоит tilda-fallback-1.0 — 1 918 байт, и это весь файл. Он делает три вещи.

Ловит отказы. Обходит все теги LINK, SCRIPT и IMG, вешает каждому onerror, а картинкам ещё и проверку «загрузилась, но ширина ноль».

Тянет спасательный код с другого домена. Не с того, который только что не ответил:

t.open("GET", "https://neo.tildacdn.com/js/tilda-fallback-advanced-1.0.min.js", !0)

Здесь .com зашит буквально — подстановки зоны в этом месте нет, в отличие от всех адресов static.

Показывает страницу силой. Два таймера в конце файла:

setTimeout(t_fallback__handleTimeout, 3e4);
setTimeout(function () {
  var t = document.getElementById("allrecords");
  if (t && !t.classList.contains("t-records_animated")) {
    var a = document.createElement("style");
    a.innerHTML = "div.t-records {opacity: 1;}";
    document.getElementsByTagName("head")[0].appendChild(a)
  }
}, 5e3);

Через 5 секунд, если у #allrecords не появился класс t-records_animated, в <head> вставляется правило opacity: 1. Отсюда знакомая картина: сайт на Тильде, который «долго думал и потом резко появился целиком». Это не загрузка закончилась — это сработал таймер. Через 30 секунд отдельный сторож ещё раз пытается вытянуть спасательный файл, если документ всё ещё грузится.

Одна деталь без смягчений: t_fallback__reloadSRC при отсутствии продвинутого файла зовёт сам себя через 500 мс — без счётчика попыток и без предела по времени. Пока neo.tildacdn.com недоступен, цикл идёт всё время, что открыта страница.

Девять атрибутов на теге #allrecords

Зона — не единственное, что рантайм читает из разметки. На снятой странице тег несёт десять атрибутов data-tilda-*; вот они и число файлов рантайма, которые их читают.

АтрибутЧитают файловЧто значит
data-tilda-root-zone10зона в адресах CDN
data-tilda-lazy9отложенная загрузка включена
data-tilda-project-id6номер проекта
data-tilda-formskey2ключ, с которым уходят формы
data-tilda-page-id1номер страницы
data-tilda-project-country1страна проекта, для маски телефона
data-tilda-cookie-type0—
data-tilda-page-alias0—
data-tilda-project-headcode0—
data-tilda-stat-scroll0—

Четыре нижних не читает ни один из 53 файлов. Оговорка та же, что и всегда: ноль означает «нет в общих файлах рантайма». Код блоков конкретной страницы приезжает своим файлом tilda-blocks-page…, и читать их может он.

Что здесь практически важно: data-tilda-formskey и data-tilda-project-id лежат в открытой разметке любой опубликованной страницы. Это не пароли, но по ним страница и опознаётся на стороне Тильды — и они уезжают вместе с каждой формой.

Как посмотреть у себя

// зона, из которой собираются все адреса CDN
document.getElementById('allrecords').dataset.tildaRootZone || 'com'

// куда эта страница отправит форму
window.tildaForm && window.tildaForm.endpoint

// сколько файлов и байт приехало с CDN Тильды
performance.getEntriesByType('resource')
  .filter(r => /tildacdn/.test(r.name))
  .reduce((a, r) => (a.n++, a.net += r.transferSize, a), { n: 0, net: 0 })

Если вторая команда вернула forms2.tildacdn.com, значит на этой странице уже была неудачная отправка и повтор израсходован: следующая ошибка повтора не получит.

Что из этого следует

Обращения к tildacdn для сайта на Тильде не побочные, а несущие: разбор того, что именно оттуда приезжает и сколько это весит, — в «Возможности Тильды». Правило одного повтора значит, что на отправку формы полагаться как на гарантию нельзя: что показать после отправки формы — про то, как это выглядит для посетителя. А если данные из формы должны куда-то попасть помимо Тильды, это уже дописывание.

Отдельный вопрос — что из этой карты остаётся, если сайт с Тильды уносить: файлы скачиваются, а адреса служб зашиты в код. Сколько именно файлов и какие службы не уедут — в «Переносе сайта с Тильды».

Вопросы по этой статье 5

Нет, это собственный домен Тильды для раздачи файлов. Если сайт сделан на Тильде, обращения к нему обязательны: оттуда приезжает весь её код. На снятой странице магазина с этого домена загружаются 20 файлов из 21 и все картинки. Домен виден в панели разработчика и в блокировщиках именно поэтому, а не из-за трекинга.