YanProfile // Spec
v0.1 · 2026-08-17

Спецификация генератора браузерных профилей для работы с Яндексом

Архитектура системы, которая создаёт Chromium-профили, неотличимые от реальных пользователей при проверке скриптами антифрода Яндекса (tmgrdfrend.fp.js, watch_serp.js, SmartCaptcha). Документ покрывает все 60+ параметров фингерпринта, систему прокси, поведенческие модели и валидацию.

Источники анализа: реверс-инжиниринг tmgrdfrend.fp.js (183 KB, 100+ параметров), анализатор pager-syzran.ru (60 проверок), мониторинг sosiska.top (версионирование скриптов), отчёт urlquery.net (сетевые запросы SmartCaptcha), архитектура Network/Monstro.

Архитектура системы

Ключевой принцип — шаблон + контролируемая мутация. Мы НЕ клонируем отпечатки реальных пользователей. Если Яндекс увидит один и тот же fingerprint hash с двух разных IP — это ещё подозрительнее синтетики. Вместо этого база реальных снапшотов даёт нам валидные комбинации параметров, а генератор создаёт на их основе уникальный профиль, которого раньше не существовало, но который выглядит так, будто мог бы существовать.

 Snapshot Collector                   Profile Generator                    Runtime Engine
 ┌────────────────────┐              ┌──────────────────────┐              ┌──────────────────────┐
 │ Реальные машины    │              │  Template Selector   │              │  Chromium Fork        │
 │ (Win/Mac/Linux)    │──собирает───▶│  выбор шаблона       │──generates──▶│  (патченный бинарник) │
 │                    │  валидные    │                      │   уникальный │                      │
 │ Что собираем:      │  комбинации │  Mutation Engine    │   профиль    │  Behavior Engine     │
 │ • GPU + extensions │              │  canvas/audio seed   │              │  (ИИ-сценарии)       │
 │ • Шрифты по OS     │              │  ±шрифты, viewport   │              │                      │
 │ • Voices по OS     │              │  уникальный hash     │              │  Cookie/State Store  │
 │ • Screen + DPR     │              │                      │              │  (персистентный)     │
 │ • Plugins + MIME   │              │  Proxy Binder       │              │                      │
 │ • WebGL precision  │              │  IP → geo → TZ       │──binds──────▶│  WebRTC TURN         │
 └────────────────────┘              └──────────┬───────────┘              └──────────┬───────────┘
                                                │                                     │
                                                ▼                                     ▼
                                     ┌──────────────────────┐              ┌──────────────────────┐
                                     │  Consistency          │              │  Runtime Validator    │
                                     │  Validator            │              │  & Script Monitor    │
                                     │                      │              │                      │
                                     │  Все параметры       │              │  Trust Score ≥ 85    │
                                     │  согласованы?        │              │  перед каждым запуском│
                                     │  Уникальность hash?  │              │  Мониторинг fp.js    │
                                     └──────────────────────┘              └──────────────────────┘

Ключевые компоненты

Snapshot Collector

Собирает с реальных машин (физических и облачных) валидные комбинации параметров: какой GPU идёт с какими WebGL extensions, какие шрифты стоят на конкретной OS, какие voices даёт Windows 11 vs macOS. Это не отпечатки для копирования — это эталоны валидных связок.

Mutation Engine

Берёт шаблон из базы и создаёт уникальный профиль: canvas seed (→ уникальный hash), audio seed, ±2-3 шрифта, рандомный viewport в реалистичном диапазоне. Результат — профиль, которого раньше не было, но все параметры внутренне согласованы.

Chromium Runtime

Патченный Chromium с подменой параметров на уровне C++ (не JS-инъекция). Canvas noise, WebGL vendor/renderer, Audio — всё через нативные хуки в движке Blink/Skia.

Consistency Validator

Проверяет, что все параметры профиля согласованы: GPU ↔ Canvas hash, OS ↔ шрифты ↔ voices, TZ ↔ IP geo, UA ↔ platform. Также проверяет уникальность — два профиля не должны дать одинаковый fingerprint.

Принцип генерации: шаблон + мутация

Три подхода к созданию профилей — и почему работает только третий:

ПодходКак работаетПроблемаРезультат
Рандом Случайная генерация каждого параметра отдельно Нарушение внутренних связей. Intel GPU + 0 расширений WebGL. Linux + шрифты Segoe UI Trust Score 20-40
Клон Точное копирование отпечатка реального пользователя Дубликат fingerprint hash с другого IP. Яндекс видит: «этот отпечаток уже есть в Москве, а теперь появился в Новосибирске». Красный флаг Детекция дубля
Шаблон + мутация Берём реальную комбинацию параметров как шаблон, мутируем уникальные компоненты (canvas seed, audio seed, ±шрифты, viewport). Все связи сохранены, hash уникален — Trust Score 85-95

Что берётся из шаблона (неизменяемое ядро)

Эти параметры жёстко связаны друг с другом. Менять один без остальных нельзя — нарушится консистентность:

  • OS + Platform — Windows 11 / macOS 14 / Ubuntu 22 → определяет всё остальное
  • GPU Vendor + Renderer — «Intel Inc.» + «ANGLE (Intel, UHD Graphics 630, ...)»
  • WebGL Extensions — набор из 30-40 расширений, привязанный к конкретному GPU
  • WebGL Precision — 12 типов точности шейдеров, зависят от GPU
  • Базовый набор шрифтов — Segoe UI есть на Windows, но не на Linux
  • Speech Voices — Microsoft David на Windows, но не на Mac
  • Math precision — зависит от версии V8, одинаковая для одной версии Chrome
  • CPU ↔ RAM корреляция — 2 ядра + 8GB = подозрительно

Что мутируется (уникальная часть)

Эти параметры делают каждый профиль уникальным, не нарушая связей:

  • Canvas noise seed → каждый профиль даёт уникальный canvas hash. Seed детерминированный: тот же профиль = тот же hash при каждом запуске
  • Audio noise seed → уникальная сумма сигнала AudioContext (диапазон 35-124)
  • Шрифты ±2-3 — из базового набора OS случайно удаляем или добавляем 2-3 редких шрифта. Пользователи устанавливают/удаляют шрифты
  • Screen / Viewport — innerWidth: 1200-1800, innerHeight: 700-1000 (в пределах screen). outerHeight = innerHeight + 80-120
  • Color scheme — light / dark (рандом, 60/40)
  • AdBlock — да/нет (35% с адблоком)
  • Permissions mix — 1-3 разрешения в "denied", остальные "prompt"
  • Media Devices — 1-3 устройства, уникальные device ID (hash от profile seed)
  • Battery level — для "ноутбука": 0.4-1.0 (рандом)
  • Network downlink — 3-15 Mbps (рандом)

Генерация за 5 шагов

1. Шаблон
Выбор из базы:
«Win11 + UHD 630 + 1080p»
→
2. Мутация
Уникальные seeds,
±шрифты, viewport
→
3. Привязка IP
Proxy → geo → TZ →
language → locale
→
4. Валидация
Все связки ok?
Hash уникален?
→
5. Профиль
JSON-конфиг для
Chromium Runtime

Пример: два профиля из одного шаблона

// Шаблон: "Win11-Intel-1080p"
// Ядро (одинаковое):
{
  os: "Windows",
  platform: "Win32",
  gpuVendor: "Intel Inc.",
  gpuRenderer: "ANGLE (Intel, Intel(R) UHD Graphics 630 ...)",
  glExtensions: ["GL_EXT_blend_minmax", "GL_EXT_color_buffer_half_float", ...], // 35 шт.
  basefonts: ["Arial", "Segoe UI", "Verdana", "Times New Roman", ...],          // 62 шт.
  voices: ["Microsoft David", "Microsoft Zira", "Microsoft Mark"],
  mathPrecision: { acos: 1.4473588658278522, sin: 0.8178819121159085, ... },
  cores: 8, memory: 8,
  screen: { width: 1920, height: 1080, dpr: 1 },
}

// Профиль A (мутация):                    // Профиль B (мутация):
{                                          {
  canvasSeed: "a7f2e9...",                   canvasSeed: "3bc841...",
  audioSeed:  "d4e1b3...",                   audioSeed:  "f8a2c7...",
  canvasHash: "38b43122",    // ← уникальный canvasHash: "7c1df890",    // ← другой
  audioSum:   101.66,        // ← уникальный audioSum:   87.23,         // ← другой
  fonts: basefonts + ["Consolas"]            fonts: basefonts - ["Georgia"]
         - ["Palatino Linotype"],                   + ["Cascadia Code"],
  innerWidth: 1583, innerHeight: 847,        innerWidth: 1412, innerHeight: 790,
  outerHeight: 939,                          outerHeight: 882,
  colorScheme: "dark",                       colorScheme: "light",
  adblock: true,                             adblock: false,
  permissions: { notifications: "denied" },  permissions: { camera: "denied" },
  mediaDevices: [                            mediaDevices: [
    { kind: "audioinput",  id: "a1b2..." },    { kind: "audioinput",  id: "x9y8..." },
    { kind: "audiooutput", id: "c3d4..." },    { kind: "videoinput",  id: "z7w6..." },
  ],                                           { kind: "audiooutput", id: "v5u4..." },
  battery: { level: 0.73, charging: false }, ],
  network: { downlink: 7.2 },               battery: { level: 1, charging: true },
}                                            network: { downlink: 12.4 },
                                           }

Модуль сбора снапшотов (Snapshot Collector)

Для качественной генерации нужна база из 100+ реальных комбинаций параметров. Снапшоты собираются с реальных физических и облачных машин.

Что собираем с каждой машины

ГруппаПараметрыКак собираем
OS Версия, билд, architecture, bitness navigator.userAgentData.getHighEntropyValues()
GPU Vendor, Renderer, WebGL version, extensions (полный список), precision (12 типов) WebGL context: getParameter(UNMASKED_VENDOR_WEBGL), getSupportedExtensions(), getShaderPrecisionFormat()
Screen width, height, availWidth, availHeight, colorDepth, DPR screen.*, window.devicePixelRatio
Fonts Полный список установленных шрифтов (100-200 кандидатов) Canvas measureText() — проверяем каждый шрифт из списка, сравнивая с fallback
Voices Список speechSynthesis голосов: name, lang, localService speechSynthesis.getVoices()
Plugins Список плагинов и MIME types navigator.plugins, navigator.mimeTypes
Media Кодеки (canPlayType для h264/vp8/vp9/av1/h265/theora), Widevine HTMLVideoElement.canPlayType(), navigator.requestMediaKeySystemAccess()
Math Точность 16 функций (sin, cos, acos, tan, etc.), Float32 NaN byte Прямой вызов Math.* с фиксированными аргументами
CPU / RAM hardwareConcurrency, deviceMemory navigator.*
Window objects Наличие chrome, RTCPeerConnection, Notification, DeviceMotionEvent и др. Проверка typeof window.X

Источники снапшотов

Физические машины

  • Собственные компьютеры (Windows, Mac, Linux)
  • Компьютеры знакомых/коллег (с разрешения)
  • Б/у ноутбуки с разными GPU
  • Приоритет: разнообразие GPU + OS версий

Облачные инстансы

  • AWS/GCP/Yandex Cloud с разными GPU
  • Виртуалки на bare metal (не nested)
  • Важно: GPU passthrough для реальных значений WebGL
  • Разные OS: Win10, Win11, macOS, Ubuntu, Fedora

Краудсорсинг (опционально)

  • Web-страница со сбором (с согласия)
  • Расширение-коллектор для Chrome
  • Анонимизация: только комбинации, без PII
  • Цель: 500+ уникальных комбинаций

Формат снапшота в базе

// Пример записи в hardware DB
{
  id: "snap_001",
  collected_at: "2026-08-15",
  source: "physical",           // physical | cloud | crowdsource

  os: {
    name: "Windows",
    version: "10.0.19045",      // Windows 10 22H2
    platform: "Win32",
    architecture: "x86",
    bitness: "64",
  },

  gpu: {
    vendor: "NVIDIA Corporation",
    renderer: "ANGLE (NVIDIA, NVIDIA GeForce GTX 1660 SUPER Direct3D11 vs_5_0 ps_5_0, D3D11)",
    webglVersion: "WebGL 1.0 (OpenGL ES 2.0 Chromium)",
    shadingVersion: "WebGL GLSL ES 1.0 (OpenGL ES GLSL ES 1.0 Chromium)",
    extensions: [
      "ANGLE_instanced_arrays", "EXT_blend_minmax", "EXT_clip_control",
      "EXT_color_buffer_half_float", "EXT_depth_clamp", "EXT_disjoint_timer_query",
      // ... 38 total
    ],
    precision: {
      vertexShaderHighFloat:   { rangeMin: 127, rangeMax: 127, precision: 23 },
      vertexShaderMediumFloat: { rangeMin: 127, rangeMax: 127, precision: 23 },
      // ... 12 types total
    },
  },

  screen: { width: 2560, height: 1440, dpr: 1, colorDepth: 24 },
  cpu: { cores: 12, memory: 16 },

  fonts: ["Arial", "Arial Black", "Calibri", "Cambria", "Cascadia Code", "Comic Sans MS",
          "Consolas", "Constantia", "Corbel", "Courier New", "Ebrima", "Gabriola",
          "Georgia", "Impact", "Lucida Console", "Malgun Gothic", "Microsoft Sans Serif",
          "Palatino Linotype", "Segoe UI", "Segoe UI Symbol", "Tahoma", "Times New Roman",
          "Trebuchet MS", "Verdana", "Webdings", "Wingdings"],  // 26 detected

  voices: [
    { name: "Microsoft David - English (United States)", lang: "en-US", local: true },
    { name: "Microsoft Zira - English (United States)", lang: "en-US", local: true },
    { name: "Microsoft Irina - Russian (Russia)", lang: "ru-RU", local: true },
  ],

  codecs: { h264: "probably", vp8: "probably", vp9: "probably", av1: "probably", h265: "", theora: "" },
  widevine: true,

  math: {
    acos: 1.4473588658278522, acosh: 691.4686750787736, asin: 0.12343746096704435,
    asinh: 0.881373587019543, atanh: 0.5493061443340549, atan: 0.4636476090008061,
    sin: 0.8178819121159085, sinh: 1.1752011936438014, cos: -0.8390715290095377,
    cosh: 1.5430806348152437, tan: -1.4214488238747245, tanh: 0.7615941559557649,
    exp: 2.718281828459045, expm1: 1.7182818284590453, log1p: 2.3978952727983707,
    powPI: 1.9275814160560206e-50,
  },
  float32NanByte: 255,

  plugins: ["PDF Viewer", "Chrome PDF Viewer", "Chromium PDF Viewer",
            "Microsoft Edge PDF Viewer", "WebKit built-in PDF"],
  windowObjects: ["chrome", "RTCPeerConnection", "Notification",
                  "XPathResult", "DeviceMotionEvent", "Intl"],
}

Минимальное покрытие базы для старта

OSGPU VendorКомбинацийПриоритет
Windows 10Intel (UHD 620/630/770)5-8Высокий — самая частая комбинация в РФ
Windows 10NVIDIA (GTX 1050-1660, RTX 3060)5-8Высокий
Windows 11Intel (Iris Xe, UHD 770)5-8Высокий
Windows 11NVIDIA (RTX 3060-4060)3-5Средний
Windows 10/11AMD (RX 580, Vega)3-5Средний
macOS 13-14Apple (M1/M2/M3)5-8Средний
macOS 12-13Intel (Iris Plus/Pro)3-5Средний
Ubuntu 22/24Intel / NVIDIA3-5Низкий — мало пользователей в РФ

Итого для MVP: 30-50 снапшотов. Для продакшена: 200+.

Полная карта параметров фингерпринта

На основе анализа tmgrdfrend.fp.js — скрипта Яндекса, который собирает отпечаток браузера. Каждый параметр имеет критичность по степени влияния на Trust Score.

ПараметрЧто проверяет ЯндексКритичностьСтратегия подмены
navigator.userAgent Консистентность с userAgentData, версия Chrome, признаки Headless CRITICAL Генерация на основе реальных UA-строк. Версия Chrome ±2 от текущей стабильной. Парсинг и кросс-валидация с brands
navigator.userAgentData
(High Entropy)
brands[], platform, architecture, bitness, uaFullVersion, wow64 CRITICAL C++ патч NavigatorUAData. Brands без HeadlessChrome. Синхронизация fullVersion с UA-строкой
navigator.platform Соответствие с OS в UA. Linux x86_64 / Win32 / MacIntel HIGH Зависит от профиля OS. Строгая связь с UA и userAgentData.platform
navigator.hardwareConcurrency Количество ядер CPU. 0 или 1 — подозрительно HIGH Значения: 2, 4, 6, 8, 12, 16. Распределение по реальной статистике. Связано с deviceMemory
navigator.deviceMemory Объём RAM в GB. Должен коррелировать с CPU HIGH Значения: 2, 4, 8. Корреляция: 2 ядра → 2-4 GB, 4+ ядер → 4-8 GB
navigator.webdriver true = 100% бот CRITICAL Патч на уровне C++: удаление флага из Blink. Не JS-override — проверяется через Object.getOwnPropertyDescriptor
navigator.maxTouchPoints Desktop = 0, мобильные > 0 MEDIUM Desktop: 0. Мобильный профиль: 5 или 10
navigator.languages Массив языков. Должен совпадать с geo HIGH Для РФ: ["ru-RU","ru","en-US","en"] или ["ru"]. Привязка к IP-геолокации
navigator.pdfViewerEnabled Наличие PDF-плагина LOW Для Chrome: true (стандартное значение)
navigator.plugins Список плагинов. Пустой = подозрительно HIGH Стандартный набор Chrome: PDF Viewer, Chrome PDF Viewer, Chromium PDF Viewer, Native Client, Chrome PDF Plugin. 5 плагинов + соответствующие MIME-типы
navigator.cookieEnabled Cookies включены MEDIUM Всегда true
navigator.vendor "Google Inc." для Chrome MEDIUM Фиксированное значение для Chrome-профиля
navigator.product
navigator.productSub
"Gecko" / "20030107" — исторические значения LOW Фиксированные значения, не менять

Screen & Display

ПараметрЧто проверяет ЯндексКритичностьСтратегия подмены
screen.width/height Разрешение экрана. Нулевые значения = headless CRITICAL Из базы реальных разрешений: 1920x1080, 1366x768, 1440x900, 2560x1440, 1536x864. Распределение по статистике РФ
screen.availWidth/Height Доступная область (минус панель задач) HIGH Windows: height - 40px (таскбар). Mac: height - 25px (меню). Linux: равно полному. Должно быть ≤ screen
screen.colorDepth
screen.pixelDepth
Глубина цвета. Всегда 24 на десктопе MEDIUM 24 для обоих значений. Всегда равны друг другу
window.devicePixelRatio DPR. 1 = обычный, 2 = Retina/HiDPI HIGH Должен коррелировать с экраном. 4K → DPR 1.5-2. 1080p → DPR 1. Mac → DPR 2
window.innerWidth/Height
window.outerWidth/Height
Размер viewport и окна. Outer > Inner HIGH Inner < availWidth. Outer = inner + хром браузера (~80-120px по высоте). Рандомизация в пределах реальных значений
screen.orientation Тип ориентации и угол LOW Desktop: "landscape-primary", angle: 0
visualViewport Параметры визуального viewport MEDIUM width/height = innerWidth/Height. scale = 1. offsetLeft/Top = 0

Canvas & WebGL

ПараметрЧто проверяет ЯндексКритичностьСтратегия подмены
Canvas Fingerprint Hash отрисовки текста/графики. Headless даёт одинаковые результаты CRITICAL Noise injection на уровне Skia (C++ патч). Добавление шума к каждому пикселю при toDataURL(). Шум должен быть детерминированным (seed от профиля) — тот же профиль = тот же hash
WebGL Vendor Производитель GPU. SwiftShader/Mesa = VM CRITICAL Реальные значения: "Intel Inc.", "NVIDIA Corporation", "ATI Technologies Inc.". Связано с Renderer
WebGL Renderer Модель GPU. Должна соответствовать Vendor и OS CRITICAL База реальных GPU: "ANGLE (Intel, Intel(R) UHD Graphics 630, ...)". Строго привязано к OS/Vendor
WebGL Extensions Количество и набор расширений HIGH 30-40 расширений для реального GPU. Набор зависит от GPU модели. Хранить в базе привязанными к конкретным renderer'ам
WebGL Precision 12 типов точности (vertex/fragment shaders) HIGH Зависит от GPU. Хранить связанными с renderer
WebGL Version Строка версии WebGL MEDIUM "WebGL 1.0 (OpenGL ES 2.0 Chromium)" — стандартная для Chrome
WebGL Shading Версия языка шейдеров MEDIUM "WebGL GLSL ES 1.0 (OpenGL ES GLSL ES 1.0 Chromium)"

Audio Fingerprint

ПараметрЧто проверяет ЯндексКритичностьСтратегия подмены
AudioContext
fingerprint
Сумма сигнала осциллятора. Нулевой результат = VM/headless CRITICAL Noise injection в OfflineAudioContext. Сумма должна быть в диапазоне 35-124. Seed от профиля для стабильности
Audio Buffer Длина буфера обработки MEDIUM Стандартное значение: 4096 или 5000 сэмплов

Fonts

ПараметрЧто проверяет ЯндексКритичностьСтратегия подмены
Font Detection Набор установленных шрифтов. Пустой = подозрительно HIGH Подмена через measureText() в Canvas API. Набор шрифтов привязан к OS. Windows: 50-100 шрифтов. Mac: 60-80. Linux: 20-40. Обязательные: Arial, Verdana, Times New Roman, Georgia, Courier New + OS-специфичные (Segoe UI для Win, SF для Mac)

Media & DRM

ПараметрЧто проверяет ЯндексКритичностьСтратегия подмены
Video Codecs Поддержка h264, vp8, vp9, av1, h265, theora MEDIUM Chrome стандарт: h264=probably, vp8=probably, vp9=probably, av1=probably, h265="", theora=""
Speech Synthesis Набор голосов. Пустой = подозрительно HIGH Подмена speechSynthesis.getVoices(). Windows: 3-5 голосов (Microsoft David, Zira). Mac: 20+ голосов. Linux: 0-2 (eSpeak). Привязка к OS
Media Devices Список устройств (камеры, микрофоны). Пустой = подозрительно HIGH Генерация 1-3 устройств: audioinput, videoinput, audiooutput. Device ID — стабильный hash от профиля
Widevine DRM Поддержка Widevine. Зависит от платформы MEDIUM Chrome desktop: поддерживается. Headless: обычно нет

Network & WebRTC

ПараметрЧто проверяет ЯндексКритичностьСтратегия подмены
WebRTC IP Leak Утечка реального IP через STUN-запросы. Несоответствие IP прокси и WebRTC = бот CRITICAL 3 режима: (1) Полная блокировка WebRTC. (2) Подмена IP через кастомный TURN-сервер. (3) Подмена SDP candidates на IP прокси. Предпочтительно: режим 2 или 3
Network Information effectiveType, downlink, rtt, saveData MEDIUM effectiveType: "4g". downlink: 5-10 Mbps (рандом). rtt: 50-150ms. saveData: false
STUN Requests Запросы к STUN-серверам (Google). Детектируются IDS HIGH Подмена STUN-сервера или проксирование через собственный TURN

Anti-Automation Detection

ПараметрЧто проверяет ЯндексКритичностьСтратегия подмены
window.webdriver
navigator.webdriver
Наличие = автоматизация CRITICAL Удаление на уровне C++ в Blink. Delete/override в JS — детектируется через property descriptor
Phantom/Nightmare
detection
window._phantom, window.__nightmare, window.callPhantom CRITICAL Не должны существовать в window. Патч Chromium: не добавлять
Selenium markers document.$cdc_, $chrome_asyncScriptInfo, __selenium_unwrapped CRITICAL Полное удаление ChromeDriver-маркеров из исходников. Патч Runtime.enable
Playwright markers __playwright, __pw_* CRITICAL Не использовать Playwright. Собственная CDP-обёртка
Puppeteer markers __puppeteer_evaluation_script__ CRITICAL Не использовать Puppeteer. Или патчить runtime
chrome object Наличие window.chrome и его свойств. Headless Chrome = отсутствует или неполный CRITICAL Полная эмуляция объекта chrome с runtime, loadTimes(), csi(). Проверка в iframe
Prototype checks HTMLElement.toString, Intl.DateTimeFormat.toString — выявляют подделку нативных функций HIGH Все подменяемые функции должны возвращать "[object Function]" или "function ... { [native code] }" через toString(). Патч на C++ уровне
eval.toString().length Длина строки eval.toString(). Разная для разных движков MEDIUM Chrome: 33. Должно быть стабильным
Error.stack Наличие и формат stack trace MEDIUM Должен быть доступен. Формат Chrome-specific

Timezone, Locale & Geo

ПараметрЧто проверяет ЯндексКритичностьСтратегия подмены
Intl.DateTimeFormat
timezone
Таймзона. Несоответствие с IP = красный флаг CRITICAL Автоматическая привязка к геолокации прокси. Москва → Europe/Moscow, Новосибирск → Asia/Novosibirsk и т.д.
Date.getTimezoneOffset() Смещение в минутах. Должно совпадать с TZ CRITICAL Автоматический расчёт из timezone. Europe/Moscow → -180
DST detection Сравнение offset января и июля для определения DST HIGH Россия: DST=false (отменён в 2014). Jan offset = Jul offset. Важно для корректности
Locale (Intl) Формат чисел, дат. Должен совпадать с language HIGH Для РФ: "ru-RU". Проверка через Intl.NumberFormat

Прочие параметры

ПараметрЧто проверяет ЯндексКритичностьСтратегия подмены
Math precision Точность 16 математических функций (sin, cos, tan, acos, asin, atan, etc.) HIGH Зависит от JS-движка и версии V8. Одинаковые для всех Chrome одной версии. Не подменять — использовать реальные значения
Float32 NaN byte Специфичное поведение NaN в Float32Array. Зависит от архитектуры CPU MEDIUM x86: byte[3] = 255 (или 127). ARM: может отличаться. Не менять для x86
Performance.now() Точность таймера. Слишком высокая = headless HIGH Ограничить точность до 0.1-1ms (стандартная для Chrome с Site Isolation). Min delta > 0
JS Heap Memory jsHeapSizeLimit, totalJSHeapSize, usedJSHeapSize. Нулевые = подозрительно MEDIUM Limit: 2-4 GB. Total > Used. Реалистичные значения: 10-50 MB used
Storage APIs localStorage, sessionStorage, indexedDB, cookies — все должны быть доступны HIGH Все = true. Блокировка = признак автоматизации
Permissions API Статус 17-24 разрешений. У реальных пользователей — mix состояний HIGH Большинство = "prompt". 1-2 = "denied" (notifications). Никогда все "granted"
Battery API Состояние батареи. Desktop = charging, level 1 MEDIUM Desktop: charging=true, level=1, chargingTime=0. Ноутбук: level 0.5-1.0, рандом
CSS Media Queries prefers-color-scheme, prefers-reduced-motion, color-gamut MEDIUM Рандомный выбор light/dark. Motion: no-preference. Gamut: srgb (или p3 для Mac)
AdBlock detection Наличие блокировщика рекламы по 4 спискам MEDIUM 30-40% профилей — с адблоком. Реалистичная пропорция. Установка uBlock Origin для части профилей
Window objects Наличие RTCPeerConnection, Notification, DeviceMotionEvent, Intl_DateTimeFormat MEDIUM Все стандартные API Chrome должны присутствовать
Notification API Permission status и constructor MEDIUM Permission: "default" или "denied". Constructor: нативный
Document Rect Размеры корневого элемента через getBoundingClientRect MEDIUM Должны соответствовать innerWidth/Height

Система прокси

Принцип: IP — это первое, что проверяется. Все остальные параметры профиля привязываются к геолокации IP. Несоответствие timezone/language/geo с IP — главный красный флаг.

Типы прокси по приоритету

ТипTrust LevelОписаниеПрименение
Резидентные (ISP) Высокий IP реальных провайдеров (Ростелеком, Билайн, МТС, Мегафон). ASN домашних пользователей Основной тип. Привязка 1 IP → 1 профиль на длительный срок
Мобильные Высокий IP мобильных операторов. Естественная ротация IP (CGNAT) Для мобильных профилей. Допускается смена IP в пределах оператора/региона
Серверные (DC) РФ Средний IP дата-центров. Легко определяются по ASN Только для тестирования. Не для продакшена
Публичные Низкий Общедоступные прокси. Забанены в базах Не использовать

Архитектура прокси-пула

ProxyPool
├── providers/
│   ├── residential/          # Резидентные провайдеры
│   │   ├── sticky sessions   # Закреплённые IP за профилем
│   │   └── geo targeting     # Город/регион → конкретный exit node
│   └── mobile/               # Мобильные провайдеры
│       ├── rotation policy   # Ротация по расписанию (каждые 4-8 часов)
│       └── operator match    # IP оператора ↔ профиль устройства
├── geo_resolver/
│   ├── ip → city             # MaxMind GeoIP2 City
│   ├── city → timezone       # Mapping города → таймзона
│   ├── city → language       # Mapping города → предпочитаемый язык
│   └── asn → isp_name        # ASN → имя провайдера (для валидации)
└── health_check/
    ├── latency monitor       # Проверка задержки каждые 5 мин
    ├── ban detection         # Мониторинг капчи/блокировок
    └── ip reputation         # Проверка IP в базах спам-листов

Правила привязки прокси к профилю

Geo Consistency

  • IP geo → timezone (автоматически)
  • IP geo → navigator.language
  • IP geo → Intl.DateTimeFormat
  • IP ASN → не DC/VPN

Session Persistence

  • 1 IP ↔ 1 профиль (sticky)
  • Ротация не чаще 1 раз / 4 часа
  • При ротации — тот же город/ISP
  • Cookie store привязан к профилю

WebRTC Sync

  • WebRTC IP = proxy IP
  • Собственный TURN-сервер
  • Блокировка STUN к Google
  • SDP candidates = proxy IP

Поведенческий движок

Яндекс анализирует поведение через watch_serp.js (108 KB, обновляется часто — 500 версий в архиве sosiska.top). Скрипт трекает: движения мыши, скролл, клики, время на странице, переходы, возвраты в выдачу.

Модель поведения на SERP

Ввод запроса
Посимвольный набор с ошибками и паузами
→
Просмотр SERP
Скролл, чтение сниппетов, 3-15 сек
→
Клик
Не первый результат, кривая Безье к ссылке
→
На сайте
30с-5мин, скролл, клики по внутренним
→
Возврат?
Pogo-sticking или остаётся

Компоненты движка

Mouse Movement

Движение мыши — основной сигнал. Прямые линии и телепортации = бот.

  • Кривые Безье с 3-5 контрольными точками + гауссов шум (sigma 2-5px)
  • Скорость: ускорение → постоянная → замедление (трапецоидальный профиль). 200-800ms на перемещение
  • Микродвижения: дрожание в покое (amplitude 1-3px, freq 2-5Hz)
  • Паузы: 50-300ms перед кликом (прицеливание). Больше пауз у "неуверенных" профилей
  • Overshoot: 10-20% перемещений проходят мимо цели и возвращаются
  • Heatmap: движения концентрируются в области контента, не по всему viewport

Scroll Behavior

  • Паттерн: не линейный. Быстрый скролл → остановка → чтение → скролл
  • Шаг: 100-400px за свайп (колесо мыши). Touchpad — плавный с инерцией
  • Обратный скролл: 5-15% времени — скролл вверх (возврат к прочитанному)
  • Глубина: не до конца страницы. 40-80% длины = реалистично

Typing Behavior

  • Скорость: 120-300ms между символами (зависит от "типа" пользователя)
  • Паузы: 300-800ms перед новым словом
  • Ошибки: 2-5% опечаток с коррекцией через Backspace
  • Автокомплит: 30-50% запросов — выбор из подсказок (клик или стрелки + Enter)

Session Patterns

  • Время сессии: 5-30 минут (Гамма-распределение, median 12 мин)
  • Запросов за сессию: 1-5 поисковых запросов
  • Глубина просмотра: 1-3 страницы выдачи (80% — только первая)
  • Pogo-sticking: 20-40% — возврат в выдачу после клика (нормально)
  • Dwell time: целевой сайт 30с-5мин, не-целевой 5-15с
  • Время суток: распределение по часам (пик 10-14 и 19-22, спад 2-6 утра)

Правила консистентности профиля

Каждый параметр связан с другими. Изолированная подмена одного значения без обновления зависимых — главная причина детекции.

СвязкаПравилоПример нарушения
UA ↔ userAgentData Версия Chrome в UA-строке = uaFullVersion. Brands не содержат HeadlessChrome UA: Chrome/150, brands: Chrome/148
UA ↔ platform OS в UA совпадает с navigator.platform и userAgentData.platform UA: Windows NT 10.0, platform: Linux x86_64
GPU ↔ Canvas hash Один и тот же GPU vendor/renderer даёт стабильный canvas. Разные GPU = разный hash Intel GPU + canvas hash от NVIDIA
GPU ↔ WebGL extensions Набор расширений зависит от GPU модели SwiftShader GPU + 40 расширений
OS ↔ Fonts Windows имеет Segoe UI, Mac — SF Pro, Linux — минимальный набор Linux platform + 80 Windows-шрифтов
OS ↔ Voices speechSynthesis голоса зависят от OS Linux + голоса Microsoft David
IP geo ↔ Timezone Строгое соответствие города IP и таймзоны IP: Москва, TZ: Asia/Bangkok
IP geo ↔ Language Язык должен соответствовать региону IP: Россия, language: zh-CN
Screen ↔ DPR ↔ Viewport innerWidth ≤ availWidth ≤ screen.width. DPR согласован innerWidth > screen.width
CPU ↔ Memory hardwareConcurrency коррелирует с deviceMemory 16 ядер + 2GB RAM
Desktop ↔ Touch Десктоп: maxTouchPoints=0, нет touch events. Мобильный: >0 Desktop UA + maxTouchPoints=5
WebRTC ↔ Proxy IP IP через WebRTC = IP прокси Proxy: 195.x.x.x, WebRTC leak: 92.x.x.x
DST ↔ Region Россия: DST=false с 2014. Jan offset = Jul offset TZ: Europe/Moscow, но DST=true

Система валидации (Trust Score)

Каждый профиль перед использованием проходит проверку. Целевой Trust Score: ≥ 85/100. Система воспроизводит логику tmgrdfrend.fp.js.

Веса параметров для Trust Score

ГруппаВесКлючевые проверки
Automation Detection 25% webdriver=false, отсутствие маркеров Selenium/Playwright/Puppeteer, chrome object полный
Canvas + WebGL + Audio 20% Уникальные хеши, реальный GPU vendor/renderer, audio сумма > 0
Navigator Consistency 15% UA ↔ userAgentData, plugins не пустые, platform ↔ OS
Geo/TZ/Language 15% IP ↔ timezone ↔ language ↔ locale. DST корректность
Screen/Viewport 10% Реалистичные размеры, inner < avail < screen, DPR корреляция
Media/Fonts/Voices 10% Шрифты ≥ 10, голоса > 0, media devices > 0
Network/WebRTC 5% Нет IP leak, Network API реалистичный

Пайплайн валидации

validate(profile) {
  score = 100

  // CRITICAL checks (fail = score 0)
  if (profile.webdriver === true)           → return 0
  if (profile.ua contains "HeadlessChrome") → return 0
  if (profile.brands contains "Headless")   → return 0
  if (profile.automationMarkers.length > 0) → return 0

  // WEIGHTED checks
  if (!matchUAvsUAData(profile))     → score -= 15
  if (!matchIPvsTimezone(profile))   → score -= 15
  if (profile.plugins.length === 0)  → score -= 10
  if (profile.fonts.length === 0)    → score -= 10
  if (profile.voices.length === 0)   → score -= 5
  if (profile.mediaDevices === 0)    → score -= 5
  if (profile.webrtcIP !== proxyIP)  → score -= 10
  if (!matchOSvsFonts(profile))      → score -= 8
  if (!matchGPUvsCanvas(profile))    → score -= 10
  if (profile.audioSum === 0)        → score -= 10
  if (!matchScreenConsistency(prof)) → score -= 5
  if (profile.batteryLevel === 0)    → score -= 3
  if (profile.performancePrecision
      < 0.01)                        → score -= 5

  return max(0, score)
}

Pipeline создания профиля

1. Select Proxy
Выбор IP из пула, резолв geo
→
2. Gen Hardware
CPU, RAM, GPU, Screen из базы
→
3. Gen Browser
UA, plugins, fonts, voices
→
4. Validate
Trust Score ≥ 85
→
5. Warm Up
Прогрев cookies/history

Детализация шагов

Шаг 1. Выбор прокси и привязка гео

selectProxy(requirements) {
  proxy = pool.getSticky(requirements.region, requirements.isp)
  geo   = geoResolver.resolve(proxy.ip)

  return {
    ip:       proxy.ip,
    port:     proxy.port,
    protocol: "socks5",
    city:     geo.city,       // "Москва"
    region:   geo.region,     // "Московская область"
    timezone: geo.timezone,   // "Europe/Moscow"
    offset:   geo.offset,     // -180
    isp:      geo.isp,        // "Rostelecom"
    asn:      geo.asn,        // AS12389
    language: geo.language,   // "ru-RU"
  }
}

Шаг 2. Генерация железа (из базы реальных снапшотов)

generateHardware(os) {
  // Выбор из базы реальных комбинаций
  snapshot = hardwareDB.sample(os)  // os: "Windows" | "Mac" | "Linux"

  return {
    cpu:     snapshot.cores,     // 4, 8, 12, 16
    memory:  snapshot.ram,       // 4, 8 (GB)
    gpu: {
      vendor:     snapshot.gpuVendor,    // "Intel Inc."
      renderer:   snapshot.gpuRenderer,  // "ANGLE (Intel, UHD 630, ...)"
      extensions: snapshot.glExtensions, // 35 extensions
      precision:  snapshot.glPrecision,  // 12 types
    },
    screen: {
      width:      snapshot.screenW,  // 1920
      height:     snapshot.screenH,  // 1080
      dpr:        snapshot.dpr,      // 1
      colorDepth: 24,
    },
  }
}

Шаг 3. Генерация браузерного профиля

generateBrowserProfile(proxy, hardware, os) {
  chromeVersion = getCurrentStableVersion() - random(0, 2)

  return {
    userAgent:     buildUA(os, chromeVersion),
    userAgentData: buildUAData(os, chromeVersion),
    platform:      platformForOS(os),
    plugins:       standardChromePlugins(),
    fonts:         fontsForOS(os),          // 20-80 шрифтов
    voices:        voicesForOS(os),         // 0-20 голосов
    mediaDevices:  generateDevices(1, 3),   // 1-3 устройства
    canvas:        { seed: randomSeed() },  // для noise injection
    audio:         { seed: randomSeed() },
    webrtc:        { mode: "proxy_ip", turnServer: "turn.our.server" },
    timezone:      proxy.timezone,
    language:      proxy.language,
    languages:     [proxy.language, "en-US", "en"],
    locale:        proxy.language,
    permissions:   generatePermissions(),   // mix prompt/denied
    battery:       { charging: true, level: 1 },
    network:       { effectiveType: "4g", downlink: random(5,10) },
    colorScheme:   random(["light", "dark"]),
    adblock:       random() < 0.35,         // 35% с адблоком
  }
}

Шаг 5. Прогрев профиля

Новый профиль без истории и cookies — подозрителен. Перед использованием в целевых задачах:

  • День 1-2: Общий сёрфинг — Яндекс главная, новости, погода, карты. 2-3 сессии по 5-10 минут
  • День 3-4: Поиск не-целевых запросов (рецепты, кино, новости). Накопление cookies Яндекс.Метрики
  • День 5+: Начало работы с целевыми запросами. Постепенное увеличение активности
  • Cookie store: Яндекс ставит yandexuid, i, yp, ys — все должны накопиться естественно
  • Периодичность: не каждый день. 3-5 дней в неделю, разное время

Классы профилей и аутентификация

Не все профили одинаково полезны. Авторизованный профиль в Яндексе весит в 3-10 раз больше анонимного для ранжирования. Система поддерживает три класса с разным уровнем доверия и ценой создания.

Три класса профилей

ПараметрAnonymousLite (рекомендуемый)Full Account
ИдентификацияТолько cookies (yandexuid)Яндекс ID через внешнюю почтуЯндекс ID + @yandex.ru + телефон
Вес сигнала1×3-5×5-10×
ТребованияНичегоEmail (Gmail и т.д.)Email + телефон + логин
Яндекс Почта——Есть (@yandex.ru)
Яндекс Диск——Есть
Отзывы/Карты—Можно оставлятьМожно оставлять
Поиск: историяТолько в cookiesПривязана к IDПривязана к ID
Верификация——Опционально (Mobile ID/ЕСИА)
Профили Яндекс ID—Один профильОбъединение до 10 по телефону
Стоимость созданияБесплатно~$0 (нужен только email)$0.05-0.30 (SMS-верификация)
Сложность автоматизацииТривиальноНизкаяСредняя (нужен SMS-сервис)
Риск банаЛегко пережитьТерпимоДорого
Доля в пуле40-50%40-50%5-15%

Lite-аккаунт: путь регистрации

Официальный путь «С любой почтой»

Яндекс поддерживает упрощённую регистрацию с внешней почтой. Это создаёт полноценный Яндекс ID, который распознаётся на поиске.

createLiteAccount(persona) {
  email = emailPool.get()      // Gmail/Outlook/Proton

  // 1. Открыть любой сервис Яндекса
  navigate("https://yandex.ru")
  click("Войти")

  // 2. Ввести внешний email как логин
  fill(loginField, email)       // user+profile42@gmail.com
  click("Войти")

  // 3. Получить код подтверждения
  code = emailPool.fetchCode(email)  // код из письма
  fill(codeField, code)

  // 4. Указать имя и фамилию персоны
  fill(firstNameField, persona.firstName)  // "Алексей"
  fill(lastNameField, persona.lastName)    // "Петров"
  click("Далее")

  // 5. Создать пароль
  fill(passwordField, generatePassword())
  click("Далее")

  // 6. Принять соглашение
  click("Зарегистрироваться")

  // Результат: активный Яндекс ID
  // Логин для входа: внешний email
  // Доступ: расширенные возможности сервисов
  // НЕТ: @yandex.ru, Диск
}

Важные ограничения и особенности

  • Социальный вход отключён: с 1 декабря 2023 регистрация через VK/Google/OK/Twitter заблокирована. Только восстановление старых аккаунтов
  • Объединение профилей: если к Lite-аккаунту привязать телефон — он объединится со всеми профилями на этом телефоне. Никогда не привязывать один телефон к нескольким профилям
  • Домены бизнес-почты: домены, подключённые к «Почта для бизнеса», нельзя использовать для Lite-регистрации
  • Gmail + aliases: Gmail поддерживает user+tag@gmail.com — каждый alias получает почту на основной ящик. Один Gmail = практически неограниченное количество Lite-аккаунтов
  • Апгрейд до Full: Lite-аккаунт можно в любой момент обновить до полного (логин + телефон). Пароль сохраняется

Рекомендуемый состав пула

Для проекта на 50-100 профилей

  • 20-25 Anonymous — дешёвые, расходные. Для объёмных сессий, разбавки. Быстрая замена при бане
  • 20-25 Lite — основная рабочая сила. Авторизованы в Яндексе, оставляют следы в системе, их сигнал весит 3-5× больше. Создание почти бесплатное
  • 5-10 Full — «тяжёлая артиллерия». Полный аккаунт @yandex.ru. Для работы с Картами, отзывами, глубокой интеграции с экосистемой. Самый дорогой сигнал

Мониторинг и адаптация

Яндекс обновляет скрипты постоянно: watch_serp.js меняется десятки раз в день (500 версий за месяцы). tmgrdfrend.fp.js — реже, но каждое обновление может добавить новые проверки. Необходим постоянный мониторинг.

Что мониторить

Script Versions

  • Хеш tmgrdfrend.fp.js каждую минуту
  • Хеш watch_serp.js каждую минуту
  • При изменении — автоматический diff
  • Алерт если появились новые API-вызовы

Captcha Rate

  • % сессий, получивших SmartCaptcha
  • Порог: < 5% = норма, > 15% = проблема
  • Привязка к конкретным профилям
  • Автоматическая ротация проблемных

Profile Health

  • Trust Score каждого профиля
  • Успешность сессий (% завершённых)
  • Роботность в Метрике (если доступна)
  • Ротация профилей с score < 70

Browser Updates

  • Новые версии Chrome Stable
  • Обновление UA-строк в базе
  • Новые API браузера
  • Изменения в поведении Chromium

Рекомендуемый технический стек

КомпонентТехнологияОбоснование
Browser Engine Chromium (собственная сборка) Полный контроль. Патчи на уровне C++ для Canvas, WebGL, Audio, Navigator, WebRTC
Profile Storage SQLite + encrypted blobs Каждый профиль = отдельный файл. Cookies, localStorage, history, cache отдельно
Profile Generator Node.js / Python Генерация JSON-конфигов из базы реальных снапшотов. Валидация консистентности
Hardware DB PostgreSQL База реальных комбинаций: GPU + Screen + Fonts + Voices. Регулярное пополнение
Behavior Engine TypeScript (в браузере) Mouse curves, scroll patterns, typing simulation. Выполняется внутри Chromium
Proxy Manager Go / Rust Высокая производительность для управления пулом. Health checks, rotation, sticky sessions
Script Monitor Node.js + cron Мониторинг изменений tmgrdfrend.fp.js и watch_serp.js. Diff + алерты
Orchestrator Python / Node.js Управление множеством профилей. Расписание сессий, балансировка нагрузки
API REST + WebSocket Управление профилями, статус сессий, мониторинг в реальном времени

Структура проекта

yanprofile/
├── chromium-patches/           # Патчи для Chromium
│   ├── navigator/              # webdriver, UA, platform, plugins
│   ├── canvas/                 # noise injection в Skia
│   ├── webgl/                  # vendor, renderer, extensions
│   ├── audio/                  # AudioContext fingerprint
│   ├── webrtc/                 # IP leak prevention
│   └── misc/                   # performance.now, battery, etc.
├── profile-generator/          # Генератор профилей
│   ├── hardware-db/            # База реальных устройств
│   ├── generators/             # Генераторы для каждой группы параметров
│   ├── validators/             # Проверки консистентности
│   └── templates/              # Шаблоны OS-специфичных профилей
├── behavior-engine/            # Поведенческий движок
│   ├── mouse/                  # Движение мыши (Безье + шум)
│   ├── scroll/                 # Паттерны скролла
│   ├── typing/                 # Набор текста с ошибками
│   ├── scenarios/              # Готовые сценарии (SERP, сайт, etc.)
│   └── timing/                 # Распределение времени и пауз
├── proxy-manager/              # Управление прокси
│   ├── pool/                   # Пул прокси с health checks
│   ├── geo-resolver/           # IP → город → timezone → language
│   ├── webrtc-turn/            # TURN-сервер для WebRTC
│   └── rotation/               # Политики ротации
├── script-monitor/             # Мониторинг скриптов Яндекса
│   ├── watchers/               # tmgrdfrend.fp.js, watch_serp.js
│   ├── diff-engine/            # Сравнение версий
│   └── alerts/                 # Уведомления об изменениях
├── orchestrator/               # Оркестратор сессий
│   ├── scheduler/              # Расписание запусков
│   ├── warmup/                 # Прогрев профилей
│   └── monitor/                # Мониторинг здоровья
└── api/                        # REST API
    ├── profiles/               # CRUD профилей
    ├── sessions/               # Управление сессиями
    └── dashboard/              # UI для мониторинга

Roadmap реализации

ФазаЗадачиРезультат
Phase 1
  • Сборка патченного Chromium (webdriver, UA, canvas noise)
  • Генератор профилей с базовой валидацией
  • Интеграция с прокси (SOCKS5)
MVP: 1 профиль проходит проверку pager-syzran.ru с Trust Score ≥ 80
Phase 2
  • WebGL/Audio fingerprint подмена
  • Font detection spoof
  • WebRTC IP sync через TURN
  • Hardware DB (100+ реальных снапшотов)
Trust Score ≥ 90. Прохождение SmartCaptcha < 5%
Phase 3
  • Behavior engine (мышь, скролл, набор)
  • Сценарии SERP-навигации
  • Система прогрева профилей
Полный цикл: генерация → прогрев → работа
Phase 4
  • Мониторинг скриптов Яндекса
  • Оркестратор множества профилей
  • API и dashboard
  • Автоматическая адаптация к изменениям
Продакшен-система с автообновлением