
В браузере есть интерфейс, о котором на рынке накрутки почти не говорят, хотя он отдаёт сайту готовый список из десятков строк — Speech Synthesis API, механизм озвучки текста. Любая страница может спросить у браузера, какими голосами он умеет читать вслух, и мгновенно получить полный перечень: названия голосов, языки, признак «локальный или облачный», служебные идентификаторы. Никаких разрешений для этого не требуется, пользователь ничего не видит и не слышит. А набор голосов — прямое следствие того, какая операционная система стоит на машине, какой она версии, какие языковые пакеты в неё доустановлены и какой браузер её обслуживает.
Именно поэтому список голосов работает как аккуратный срез системы, и именно поэтому ферма профилей на нём горит. Сорок виртуалок, развёрнутых из одного образа, отдают одинаковый перечень до последней буквы. Сервер без звуковой подсистемы отдаёт пустой массив, и это ещё заметнее. Ниже — как устроен сигнал, как антифрод превращает его в детектор кластеров и что нужно сделать, чтобы голосовой набор профиля выглядел как у живого человека. Тема примыкает к материалам про AudioContext-фингерпринт и аппаратный отпечаток железа.
Что именно отдаёт браузер
Вызов метода получения голосов возвращает массив объектов. Каждый объект — это один синтезированный голос, и в нём содержится больше полезного для идентификации, чем кажется на первый взгляд:
- Название голоса. Человекочитаемая строка вида «имя голоса плюс язык». Названия строго привязаны к платформе: у Windows свои, у macOS свои, у Android свои, у голосов от облачных движков — третьи. Подделать одно название легко, весь согласованный перечень — нет.
- Языковой тег. Язык и региональный вариант для каждого голоса. Отсюда видно, какие языковые пакеты стоят в системе, и это должно биться с языком интерфейса и геолокацией.
- Признак локальности. Голос обслуживается локальным движком системы или тянется из облака. Соотношение локальных и сетевых голосов различается по платформам и версиям.
- Служебный идентификатор. Внутренний ключ голоса, зачастую содержащий путь или системное имя движка. Это самая «говорящая» часть: она выдаёт не только платформу, но иногда и конкретную сборку.
- Признак голоса по умолчанию. Один из голосов помечен как основной. Какой именно — зависит от языка системы и её настроек.
- Порядок элементов в массиве. Сам по себе не случаен: он определяется тем, как система регистрирует движки. Одинаковый порядок у сотни визитов — самостоятельный признак.
Общий объём информации сопоставим со списком шрифтов, но добывается он проще: одна строка кода, один синхронный или почти синхронный ответ, никаких измерений и хитростей. При этом закрывают этот параметр единицы инструментов — а значит, для антифрода он ценнее массово подменяемых сигналов.
Список голосов — это оглавление операционной системы. По нему видно, какая платформа, какого поколения, с какими языковыми пакетами и на каком браузере. И всё это отдаётся страницей без единого запроса разрешений.
Почему набор голосов так хорошо различает системы
Платформа задаёт скелет
Каждая операционная система несёт собственный речевой движок со своим набором голосов. Совпадений между платформами почти нет: набор, характерный для настольной Windows, физически не может присутствовать на мобильном Android, и наоборот. Поэтому первое, что делает проверяющий скрипт, — сверяет «платформу из голосов» с платформой, заявленной в user-agent. Рассинхрон здесь означает подмену и ловится тривиально, ровно как в истории с user-agent и историей кук.
Версия системы задаёт детали
Внутри одной платформы набор меняется от поколения к поколению: старые голоса выводятся из состава, новые добавляются, меняются названия и внутренние идентификаторы. Профиль, заявляющий свежую сборку системы, но отдающий голоса, снятые с поддержки несколько лет назад, — противоречие, которое видно без всякого машинного обучения.
Языковые пакеты задают индивидуальность
Самая «личная» часть набора. Человек, который ставил дополнительный язык для работы или учёбы, получает вместе с ним голоса этого языка. Двуязычные пользователи, жители приграничных регионов, те, кто пользуется распознаванием речи, — у всех перечень различается. Именно этот слой создаёт разброс в живой популяции, и именно его нет у клонов из одного образа.
Браузер добавляет свой слой
Разные браузерные движки по-разному подхватывают системные голоса и по-разному добавляют собственные. Один движок отдаёт голоса ровно те, что зарегистрированы в системе; другой подмешивает собственные облачные. Отсюда ещё одна проверка на согласованность: набор обязан соответствовать не только системе, но и заявленному браузеру.
Таблица: слои голосового набора и что они выдают
| Слой набора | Что определяет | Типовая ошибка фермы |
|---|---|---|
| Платформенные голоса | операционная система и её семейство | десктопный набор при мобильном user-agent |
| Версия сборки | поколение системы | снятые с поддержки голоса в «свежей» системе |
| Языковые пакеты | языки пользователя, косвенно — регион | у всех профилей ровно один язык |
| Локальные и облачные | тип речевого движка | только облачные при отсутствии сети в профиле |
| Служебные идентификаторы | конкретная сборка движка | идентификаторы хост-машины протекают наружу |
| Порядок и голос по умолчанию | порядок регистрации движков в системе | идентичный порядок на всей ферме |
Обратите внимание на предпоследнюю строку. Служебные идентификаторы — та часть, которую почти никто не проверяет вручную, а между тем через них реальная хост-система протекает наружу даже при подменённых человекочитаемых названиях. Механика та же, что с утечками в WebRTC и DNS: подменили витрину, забыли про служебный слой.
Как антифрод превращает список голосов в детектор фермы
Алгоритм простой и дешёвый в вычислении, что для промышленной антибот-системы важнее изящества:
- Снятие. Скрипт получает массив голосов и сворачивает его в хеш: названия, языки, признаки локальности, порядок. На выходе — одна короткая строка, удобная для сравнения.
- Кластеризация. Визиты группируются по совпадению хеша. Живая аудитория даёт длинный хвост из множества вариантов; ферма даёт один-два значения на тысячи сессий.
- Сверка с окружением. Платформа из голосов сопоставляется с user-agent, языком интерфейса, часовым поясом и геолокацией прокси. Любое расхождение — минус к доверию.
- Поиск аномалий. Пустой список, набор из одного голоса, набор из несуществующей комбинации языков — всё это выделяется в отдельные подозрительные группы.
- Проверка стабильности. При повторном визите с теми же куками набор голосов обязан совпасть. Смена перечня у «того же человека» означает генерацию на лету.
Отдельный случай: пустой список
Серверная машина без звуковой подсистемы и без установленных речевых пакетов отдаёт пустой массив. Многие считают это безопасным состоянием: нет данных — нет отпечатка. На практике это худший из возможных вариантов. Пустой список сам по себе является значением, причём редким: у подавляющего большинства живых устройств голоса есть, потому что они идут в комплекте с системой. Профиль без единого голоса не растворяется в толпе — он образует собственную узкую группу, куда попадают преимущественно автоматизированные окружения. Это ровно та же логическая ошибка, что с отключением графических API: отсутствие сигнала само становится сигналом.
Второй по частоте случай: ленивая загрузка
Есть техническая тонкость, на которой палятся сценарии автоматизации. В ряде браузеров список голосов заполняется асинхронно, и при мгновенном обращении сразу после загрузки страницы возвращается пустой массив, который через доли секунды становится полным. Живой пользователь физически не успевает ничего сделать за это время, а скрипт — успевает. Если счётчик видит серию событий, где обращение к странице произошло раньше, чем система вообще успела зарегистрировать голоса, это косвенный признак машинного темпа. Тема смыкается с эмуляцией мыши и биометрией поведения: машину выдаёт не столько значение параметра, сколько скорость обращения к нему.
Таблица: живая аудитория против фермы по голосам
| Признак | Живая аудитория | Ферма из одного образа |
|---|---|---|
| Число голосов в списке | широкий разброс по платформам | одно и то же число у всех |
| Хеш перечня | сотни вариантов | одно-два значения |
| Языки голосов | у части профилей два и более | ровно один у всех |
| Пустой список | редкость | частый случай на серверах |
| Согласованность с user-agent | полная | десктопные голоса при мобильной подмене |
| Стабильность между визитами | набор не меняется | перечень плавает при пересоздании профиля |
Как маскировать голосовой набор правильно
Эталонные наборы под платформу
Работающий подход один: держать библиотеку эталонных перечней, снятых с реальных систем, и подставлять профилю целиком один из них. Не генерировать названия, не перемешивать голоса разных платформ, не выдумывать языки — брать готовый согласованный набор, который существует в природе. Тот же принцип, что с лимитами графического адаптера: набор параметров важнее отдельного параметра.
Согласованность с языком и геолокацией
Профиль, который выходит через прокси одного региона, заявляет соответствующий язык интерфейса и часовой пояс, обязан иметь голоса этого языка в наборе. Обратное тоже верно: экзотические языковые голоса при полном отсутствии других признаков связи с регионом выглядят странно. Это продолжение общей темы согласованности, разобранной в материале про рассинхрон часового пояса и языка.
Стабильность в рамках профиля
Один профиль — один набор голосов на весь срок жизни. Если сегодня у профиля восемь голосов, а завтра двенадцать, при том что куки, разрешение экрана и прочее сохранились, — перед антифродом не человек, который что-то доустановил, а генератор, который перегенерировал параметры. Изменения допустимы, но редкие и логичные: доустановка языкового пакета случается, массовая смена всего набора — нет.
Естественное распределение по парку профилей
Наборы голосов по ферме должны распределяться примерно как в реальной популяции: преобладают массовые версии популярных систем, меньше — редкие, единицы — экзотика с несколькими языковыми пакетами. Ферма, где у каждого профиля уникальный богатый набор из пяти языков, статистически невозможна не меньше, чем ферма клонов.
Не обнулять и не ломать
Соблазн вырезать интерфейс целиком или заставить его возвращать пустой массив надо гасить на старте. Отсутствие голосов — аномалия. Выброшенный из окружения метод — ещё большая аномалия, потому что скрипт видит не пустой список, а отсутствие самого метода там, где он обязан быть в любом современном браузере.
Чек-лист проверки профилей
- Откройте с трёх-четырёх профилей страницу, выводящую список голосов, и сравните перечни между собой. Они обязаны различаться.
- Убедитесь, что список не пуст. Профиль без голосов требует починки окружения, а не «принятия как есть».
- Сверьте платформу из названий голосов с тем, что заявляет user-agent: мобильный профиль не может нести настольный набор.
- Проверьте служебные идентификаторы: в них не должно быть признаков реальной хост-машины и путей сервера.
- Сверьте языки голосов с языком интерфейса, часовым поясом и регионом прокси.
- Повторите замер через сутки на тех же профилях: набор обязан совпасть с предыдущим.
- Оцените разброс по всему парку: если хеш перечня один на всю ферму, маскировки нет.
Разбор кейса: ферма, которую склеили по одной строке
Проект в конкурентной тематике работал на связке из платного антидетекта и мобильных прокси. Графика подменялась, аудиоотпечаток шумился, шрифты имели маски, поведение было близко к человеческому. Первые недели показывали рост, затем динамика встала, а качество трафика по внутренним метрикам поползло вниз: визиты доходили до сайта, но вес их явно снижался.
Диагностику начали с полного дампа окружения профилей, а не с привычного короткого чек-листа. Список голосов оказался идентичным у всех профилей парка: одинаковые названия, одинаковый порядок, один язык, одинаковые служебные идентификаторы, унаследованные от образа виртуальной машины, из которого разворачивались все узлы. При этом user-agent у половины профилей заявлял мобильные устройства, а голоса были настольные — то есть профиль противоречил сам себе на уровне одной строки кода.
Лечение состояло из двух шагов. Сначала собрали библиотеку эталонных перечней с реальных устройств разных платформ и версий и раздали их профилям так, чтобы распределение по парку напоминало живую популяцию, с преобладанием массовых конфигураций. Затем закрепили наборы за профилями жёстко, чтобы они не пересоздавались при перезапуске, и добавили сверку голосов с языком и регионом прокси в предстартовую проверку. После этого отсев прекратился, а динамика вернулась в течение нескольких недель. Практический вывод простой: дыру ищут не там, где сложно, а там, где никто не смотрел.
Частые ошибки
- Считать голосовой интерфейс бесполезным. «Кто вообще пользуется озвучкой» — не аргумент: параметр читает не пользователь, а скрипт, и читает всегда.
- Отдавать пустой список. Отсутствие голосов не прячет профиль, а помещает его в узкую аномальную группу.
- Удалять сам метод из окружения. Ещё грубее пустого списка: отсутствие стандартного интерфейса в современном браузере невозможно.
- Подменять названия, забыв про идентификаторы. Служебный слой продолжает выдавать хост-систему, и вся маскировка становится бессмысленной.
- Игнорировать связь с языком и регионом. Набор голосов, не имеющий отношения к заявленной географии, ломает связку так же надёжно, как утечка адреса.
Частые вопросы
Правда ли, что список голосов читается вообще без разрешений? Да. Это обычный синхронный интерфейс браузера, доступный любой странице. Пользователь не видит запроса и не слышит звука — данные снимаются молча, как и большинство отпечатков окружения.
Закрывают ли этот параметр антидетект-браузеры? Часть инструментов закрывает, часть — нет, а часть закрывает формально, подменяя человекочитаемые названия и оставляя служебные идентификаторы нетронутыми. Ориентироваться нужно не на описание инструмента, а на собственный замер по своим профилям.
Насколько это критично на фоне графических отпечатков? Сам по себе набор голосов даёт меньше энтропии, чем графика, но он почти не подменяется и отлично работает как признак согласованности. Для антифрода ценность сигнала во многом определяется тем, насколько массово его закрывают, — а здесь закрывают редко.
Снимают ли проблему реальные устройства? Снимают полностью: у физического телефона набор голосов настоящий, согласованный с системой и естественно разный у разных аппаратов. Это очередной довод в пользу гибридной схемы, где ядро трафика идёт с физических аппаратов, а объём добирается качественной эмуляцией.
Вывод
Речевой интерфейс браузера отдаёт любой странице развёрнутый срез системы: названия голосов, их языки, тип движка, служебные идентификаторы, порядок регистрации и голос по умолчанию — и всё это без разрешений и без единого звука. Набор напрямую зависит от платформы, версии сборки, языковых пакетов и браузера, поэтому у живой аудитории он даёт длинный хвост вариантов, а у фермы из одного образа сворачивается в одно значение на весь парк; пустой список тоже не спасает, потому что образует собственную узкую аномальную группу. Правильная работа сводится к пяти вещам: подставлять целиком эталонные наборы, снятые с реальных систем, держать их согласованными с user-agent, языком, часовым поясом и регионом прокси, закреплять набор за профилем на весь срок его жизни, распределять конфигурации по парку как в живой популяции и никогда не пытаться решить задачу обнулением. Проверяется всё это за десять минут, а стоит ошибка — месяцев работы, поэтому голосовой набор стоит внести в обязательный предстартовый чек-лист рядом с графикой, шрифтами и сетевым отпечатком.
Больше о поведенческом продвижении и других услугах — на главной странице ProfSEO24.
Закажите накрутку ПФ в ProfSEO24
Выводим сайты в ТОП-1 Яндекса за счёт поведенческих факторов на базе ИИ — без риска фильтров. Более 300 сайтов в ТОП-1, первые сдвиги по позициям за 3 дня. Рассчитаем стоимость под вашу нишу и регион.
Заказать накрутку ПФ Написать в TelegramКомментарии
Павел Ершов
Проверил парк из тридцати профилей — перечень голосов совпал у всех до последнего элемента, включая порядок. Про этот параметр я вообще ни разу не думал за три года работы.
Admin
Типовая картина для парка, развёрнутого из одного образа. Начните не с подмены, а с инвентаризации: снимите хеш перечня по каждому профилю и посмотрите, сколько уникальных значений получилось. Если одно — это ваша главная точка отказа, и прокси тут ни при чём.
Вадим Зарубин
А если просто заставить метод возвращать пустой массив? Это же проще, чем собирать библиотеку эталонов.
Admin
Проще, но хуже. Пустой список — это не «нет данных», это конкретное редкое значение. У живых устройств голоса идут в комплекте с системой, поэтому профиль без единого голоса попадает в узкую группу, где почти нет людей. Вы не прячетесь, а подсвечиваете себя. Эталоны собираются один раз и потом работают годами.
voice_hunter
Служебные идентификаторы — вот где собака зарыта. Названия у меня подменялись нормально, а внутренние ключи честно отдавали систему сервера. Полез смотреть только после этой статьи.
Аркадий Зуев
Момент с порядком элементов в массиве отдельно порадовал. Даже если названия разные, порядок регистрации движков сам по себе сигнал. Об этом вообще нигде не пишут.
Жанна Перевозчикова
Мобильный user-agent и настольный набор голосов — это же самоубийство. И проверяется в две строки. Сколько таких связок в природе ходит, страшно представить.
Егор Сафиуллин
Вопрос по распределению: если раздать всем профилям разные наборы, но каждому богатый, с несколькими языками, это же лучше чем одинаковые?
Admin
Лучше, но всё равно неправильно. Парк, где у каждого профиля пять языковых пакетов, так же неестественен, как парк клонов, просто аномалия другая. В живой популяции преобладают массовые конфигурации с одним языком, реже встречаются двуязычные, и совсем единицы — с экзотикой. Целиться надо в эту форму распределения, а не в максимальное разнообразие.
Нина Абрамова
Про асинхронное заполнение списка — тонко. Живой человек не успеет прочитать массив раньше, чем система его зарегистрирует, а скрипт успевает. Сам темп обращения выдаёт машину.
stage_builder
Собрал библиотеку эталонов с реальных устройств знакомых, вышло около двадцати наборов. Немного, но разброс уже появился. Дальше буду добирать.
Admin
Двадцать наборов на небольшой парк — уже рабочая база, особенно если раздавать их не поровну, а с перекосом в сторону массовых конфигураций. Только следите, чтобы один набор не приходился на слишком большую долю профилей: доля одного хеша в вашем трафике должна быть сопоставима с его долей в реальной популяции, а не составлять половину визитов.
Валентин Кочубей
Кейс узнал в своём проекте. Полгода искали проблему в прокси и поведении, а она сидела в строке, которую никто не читал. Дыру ищут не там, где сложно — согласен на сто процентов.
Оксана Ремизова
Получается, чем реже параметр подменяют, тем он ценнее для антифрода. Логика жестокая, но понятная: закрытое всеми перестаёт различать.
Тимур Бекетов
А как часто допустимо менять набор у живущего профиля? У человека же реально может появиться новый язык в системе.
Admin
Может, и такие изменения вполне естественны, но они редкие и однонаправленные: голоса чаще добавляются, чем исчезают, и добавляется обычно один язык, а не три. Безопасная практика — не трогать набор вообще в течение рабочего цикла профиля, а если очень хочется реализма, менять его у небольшой доли профилей и только в сторону расширения.
Руслан Хабибуллин
Отдельно отмечу мысль про удаление самого метода. Это же ещё заметнее пустого списка: в современном браузере интерфейс обязан быть, и его отсутствие кричит громче любого значения.
Алевтина Сорокина
Добавлю из практики: связку голосов с регионом прокси мы засунули в предстартовую проверку скриптом. Если язык голосов не бьётся с географией выхода, профиль просто не стартует. Дёшево и снимает целый класс ошибок.
Геннадий Плужник
Работаю с ProfSEO24 второй сезон. Что ценно — объясняют механику, а не продают волшебство: показали дамп окружения моих профилей, ткнули в конкретные расхождения и сказали, что чинить в каком порядке. После такого разговора начинаешь понимать, за что платишь.