Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
urx — Извлекает URL-адреса из архивов OSINT для аналитики безопасности | Kitploit
Инструменты/GitHubGitHub/hahwul/urx
OSINT (Разведка открытых источников)РазведкаСбор информацииВеб-безопасностьКраулер
GitHubhahwul/urx

urx

Извлекает URL-адреса из архивов OSINT для аналитики безопасности

Репозиторий
19020151 день назадПроверено Kitploit

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться
Сайт
Urx Logo

Извлекает URL-адреса из OSINT-архивов для анализа безопасности.

Urx — это инструмент командной строки, предназначенный для сбора URL-адресов из OSINT-архивов, таких как Wayback Machine и Common Crawl. Написанный на Rust для обеспечения эффективности, он использует асинхронную обработку для быстрого опроса нескольких источников данных. Этот инструмент упрощает процесс сбора информации об URL-адресах для указанного домена, предоставляя исчерпывающий набор данных, который может быть использован для различных целей, включая тестирование безопасности и анализ.

Возможности

  • Параллельное получение URL-адресов из нескольких источников (Wayback Machine, Common Crawl, OTX, Arquivo.pt)
  • Подключение любого другого CDX-сервера индексов — национальных веб-архивов, частного pywb, OutbackCDX — с помощью --cdx-endpoint URL, без изменения кода
  • По умолчанию без ключей: Wayback, Common Crawl, OTX, Arquivo.pt и URLScan (анонимно) работают без API-ключа
  • Провайдер BeVigil: URL-адреса, извлечённые из распакованных Android-приложений — эндпоинты, которые не обходил ни один веб-архив
  • Поддержка ротации API-ключей для провайдеров VirusTotal и URLScan для смягчения ограничений скорости
  • Аутентифицированное тестирование: -H, --cookie и --user-agent применяются к каждому запросу, который urx делает к цели (--check-status, --extract-links, --extract-js-endpoints, --expand-specs), и намеренно никогда не отправляются в архив
  • Фильтрация результатов по расширениям файлов, подстрокам или полным регулярным выражениям (--match-regex / --filter-regex)
  • Предопределённые пресеты, как по семейству файлов ("no-images", "only-js"), так и по интересу безопасности ("only-secrets", "only-backup", "only-config", "only-api")
  • Фильтрация на стороне архива: передача кода состояния, MIME-типа и диапазона дат непосредственно в CDX-запрос, чтобы отфильтрованные захваты вообще не пересекали сеть
  • Клиентская фильтрация метаданных (--meta-*): фильтрация по дате первого/последнего захвата, записанному MIME-типу и записанному статусу единообразно для каждого провайдера, после сбора
  • Цели с ограничением по пути: urx example.com/shop передаёт область в сам CDX-запрос (url=example.com/shop*), поэтому поддерево большого сайта стоит лишь часть всего индекса вместо фильтрации на стороне клиента
  • Файлы области bug-bounty (--scope-file): собственный список *.example.com / !admin.example.com программы, используемый дословно, повторяемый и объединяемый, при этом исключения всегда побеждают
  • Нормализация и дедупликация URL-адресов: сортировка параметров запроса, удаление завершающих слешей, объединение семантически идентичных URL-адресов и схлопывание почти-дубликатов, отличающихся только идентификаторами, хешами или датами (--dedup-similar)
  • Поддержка нескольких форматов вывода: обычный текст, JSON, JSON Lines, CSV и wordlist — сегменты пути и имена параметров, из которых построена цель, без идентификаторов, хешей и дат
  • Представления параметров и фаззинга: --params (полный перечень параметров цели), --params-by-endpoint (какой эндпоинт принимает что) и --fuzz-placeholder FUZZ (один шаблонный URL на каждую сигнатуру параметра, готовый для ffuf или dalfox)
  • Метаданные захвата архива: first_seen, last_seen, mime, archive_status и digest возвращаются с каждым URL-адресом, о котором сообщил CDX-архив, без дополнительных сетевых затрат
  • Потоковый вывод (--stream): URL-адреса записываются по мере их сообщения каждым провайдером, поэтому конвейер начинает работать немедленно, вместо ожидания самого медленного архива
  • Поддержка прямого ввода файлов: чтение URL-адресов непосредственно из WARC-файлов, сжатых файлов URLTeam и текстовых файлов
  • Вывод результатов в консоль или файл, либо потоковая передача через stdin для интеграции в конвейер
  • Тестирование URL-адресов:
    • Фильтрация и проверка URL-адресов на основе кодов состояния HTTP и шаблонов.
    • Извлечение дополнительных ссылок из собранных URL-адресов — якорей, скриптов, таблиц стилей, действий форм, iframe, изображений, медиа-источников, объектов, встраиваний и целей meta-refresh
    • Извлечение из архивных тел ответов собранных URL-адресов (--archive-body), чтобы страницы, которых больше не существует, всё ещё отдавали содержавшиеся в них ссылки — один запрос на каждое отдельное тело, благодаря дедупликации по CDX-дайджесту
    • С --extract-js-endpoints извлекайте также из архивного JavaScript: бандл, названный по хешу сборки, отдаёт 404 в момент повторного развёртывания сайта, и архив — единственное место, где его API-поверхность всё ещё существует
    • Сохраняйте воспроизведённые тела (--archive-body-dir) как корпус для поиска того, что не ищет ни один извлекатель ссылок — комментариев разработчиков, встроенных учётных данных, внутренних имён хостов — без дополнительных запросов
    • Разворачивание спецификаций API (--expand-specs): документы OpenAPI 3.x, Swagger 2.0 и GraphQL introspection, в формате JSON или YAML, превращаются в каждый описанный ими маршрут — один запрос даёт всю документированную поверхность
    • Метаданные ответа: --check-status также записывает Location, Content-Length и Content-Type, а --check-title добавляет HTML
  • Обнаружение архивных robots.txt и sitemap.xml (--archived-discovery): каждая отдельная версия, которую хранит Wayback Machine, поэтому Disallow: от 2015 года всё ещё называет пути, о которых сайт с тех пор перестал упоминать
  • Кэширование и инкрементальное сканирование:
    • Локальное кэширование в SQLite или удалённое в Redis для избежания повторного сканирования доменов
    • Инкрементальный режим для обнаружения только новых URL-адресов с момента последнего сканирования
    • Настраиваемый TTL кэша и автоматическая очистка устаревших записей
    • Подкоманда urx cache для просмотра и обслуживания кэша: stats, list, prune, drop <domain>, clear

Preview

Установка

Из Cargo```bash

https://crates.io/crates/urx

cargo install urx

root@kitploit:~
### Из Homebrew```bash
# https://formulae.brew.sh/formula/urx
brew install urx

Из исходного кода```bash

git clone https://github.com/hahwul/urx.git cd urx cargo build --release

root@kitploit:~
Скомпилированный бинарный файл будет доступен по пути `target/release/urx`.

### Из Docker

[ghcr.io/hahwul/urx](https://github.com/hahwul/urx/pkgs/container/urx)

### Автодополнение для оболочки

`urx` генерирует собственный скрипт автодополнения, поэтому он всегда соответствует флагам
того бинарного файла, который у вас фактически установлен.```bash
# zsh — any directory on your $fpath works
urx --completions zsh > ~/.zfunc/_urx
# (make sure ~/.zfunc is on the fpath, then `compinit`)

# bash
urx --completions bash > ~/.local/share/bash-completion/completions/urx

# fish
urx --completions fish > ~/.config/fish/completions/urx.fish

powershell и elvish также поддерживаются. Флагу не требуется целевой домен.

Страница руководства```bash

urx --manpage > ~/.local/share/man/man1/urx.1 man urx

root@kitploit:~
## Использование

### Базовое использование```bash
# Scan a single domain
urx example.com

# Scan multiple domains
urx example.com example.org

# Scan domains from a file
cat domains.txt | urx

Опции```

Usage: urx [OPTIONS] [DOMAINS]... [COMMAND]

Commands: cache Inspect and maintain the URL cache: stats, list, prune, drop ..., clear

Arguments: [DOMAINS]... Domains to fetch URLs for

Options: -c, --config Config file to load --provider-config Separate provider config file holding only API keys (default: $XDG_CONFIG_HOME/urx/provider-config.toml). CLI/env > provider-config > main config. --completions Print a shell completion script (bash, zsh, fish, powershell, elvish) to stdout and exit --manpage Print the roff man page to stdout and exit -h, --help Print help -V, --version Print version

Input Options: --files ... Read URLs directly from files (supports WARC, URLTeam compressed, and text files) --domain-list File of newline-separated domains to scan (repeatable; merged with positional DOMAINS and stdin; # comments allowed)

Output Options: -o, --output Output file to write results --output-dir Write one file per domain into this directory (extension matches --format). Coexists with --output / stdout. -f, --format Output format: "plain", "json" (one array), "jsonl" (one JSON object per line), "csv", "wordlist" (path segments and parameter names, deduplicated and sorted) [default: plain] --stream Write URLs as each provider reports them instead of once at the end (unsorted; bypasses cache; rejects options needing the full result set) --merge-endpoint Merge endpoints with the same path and merge URL parameters --normalize-url Normalize URLs for better deduplication (sorts query parameters, removes trailing slashes) --dedup-similar Collapse URLs that differ only in variable data (numeric ids, UUIDs, hashes, dates, query values) --params Replace the URL list with every query parameter name the run saw, once each --params-by-endpoint One line per endpoint: the endpoint and the comma-separated union of the parameter names seen on it (id-looking path segments collapse to {id}) --fuzz-placeholder Replace every query parameter value with VALUE, keeping one URL per parameter signature — output you can feed straight to ffuf or dalfox

Provider Options: --providers Providers to use (comma-separated, e.g., "wayback,cc,otx,arquivo,vt,urlscan") [default: wayback,cc,otx] --exclude-providers <EXCLUDE_PROVIDERS> Providers to exclude (comma-separated). Wins on conflict with --providers / --all-providers. --all-providers Enable every supported provider. API-keyed providers only activate when a key is available. --list-providers List every supported provider then exit. --subs Include subdomains when searching --cc-index <CC_INDEX> Common Crawl index to use; accepts comma-separated list to query multiple indexes in parallel (e.g. CC-MAIN-2026-17,CC-MAIN-2025-51). latest (the default) resolves the newest via collinfo.json. [default: latest] --cdx-endpoint Query an additional CDX index server (any pywb, OutbackCDX, or classic Internet-Archive-style CDX API) by its full API URL, e.g. https://vefsafn.is/cdx. Repeatable. Each endpoint becomes a provider with id cdx:<host> and honours --subs, --from/--to and the --archive-* filters. See "Custom CDX Endpoints" below --cdx-dialect Which CDX dialect the --cdx-endpoint servers speak: pywb or classic. Unset: urx probes each endpoint once and falls back to pywb when the answer is ambiguous --from Restrict every CDX-backed provider (wayback, cc, arquivo, --cdx-endpoint) to captures at or after DATE (YYYY/YYYYMM/YYYYMMDD/YYYYMMDDhhmmss). Alias: --wayback-from --to Restrict every CDX-backed provider to captures at or before DATE (same format as --from). Alias: --wayback-to --archive-status Keep only captures the archive recorded with this HTTP status code (e.g. "200"). Applied by the CDX index itself, so unlike --include-status it costs no extra requests. A multi-value list works on wayback only — see "Archive-side Filtering" below --archive-exclude-status Drop captures the archive recorded with these HTTP status codes (comma-separated, e.g. "404,500"). Multi-value works on every CDX provider --archive-mime Keep only captures with this recorded MIME type (e.g. "application/json"). Catches endpoints with no file extension, which -e/--extensions cannot --archive-exclude-mime Drop captures with these recorded MIME types (comma-separated, e.g. "text/html,image/png") --vt-api-key <VT_API_KEY> API key for VirusTotal (can be used multiple times for rotation, can also use URX_VT_API_KEY environment variable with comma-separated keys) --urlscan-api-key <URLSCAN_API_KEY> Optional API key for Urlscan; the provider also works anonymously (rate-limited ~30 req/min per IP). Can be used multiple times for rotation, or via URX_URLSCAN_API_KEY (comma-separated keys) --github-api-key <GITHUB_API_KEY> Personal access token for the GitHub Code Search provider (also reads URX_GITHUB_API_KEY, comma-separated for rotation) --bevigil-api-key <BEVIGIL_API_KEY> API key for BeVigil, which returns URLs extracted from unpacked Android apps (also reads URX_BEVIGIL_API_KEY, comma-separated for rotation). Required for the provider

Скачать инструмент
<title>
bevigil

Discovery Options: --exclude-robots Exclude robots.txt discovery --exclude-sitemap Exclude sitemap.xml discovery --archived-discovery Also read every distinct archived version of robots.txt and sitemap.xml the Wayback Machine holds --archived-discovery-limit Maximum archived documents fetched per domain by each archived provider (nested sitemaps count) [default: 50]

Display Options: -v, --verbose Show verbose output --silent Silent mode (no output) --no-progress No progress bar --no-color Disable ANSI color in the progress UI and output (NO_COLOR is also honored) --show-sources Annotate output URLs with the providers that returned them --show-meta Annotate plain-text URLs with the archive capture metadata --stats Print a per-provider summary to stderr at end of run

Filter Options: -p, --preset Filter Presets (e.g., "no-resources,no-images,no-audio,only-js,only-style,only-secrets,only-backup,only-config,only-api") -e, --extensions Filter URLs to only include those with specific extensions (comma-separated, e.g., "js,php,aspx") --exclude-extensions <EXCLUDE_EXTENSIONS> Filter URLs to exclude those with specific extensions (comma-separated, e.g., "html,txt") --patterns Filter URLs to only include those containing specific patterns (comma-separated) --exclude-patterns <EXCLUDE_PATTERNS> Filter URLs to exclude those containing specific patterns (comma-separated) --match-regex Keep only URLs matching this regular expression (repeatable, ORed; case-sensitive; never comma-split) --filter-regex Drop URLs matching this regular expression (repeatable; one match is enough) --show-only-host Only show the host part of the URLs --show-only-path Only show the path part of the URLs --show-only-param Only show the parameters part of the URLs --min-length <MIN_LENGTH> Minimum URL length to include --max-length <MAX_LENGTH> Maximum URL length to include --strict Enforce exact host validation (default) --no-strict Disable host validation (keep URLs on any host a provider returns). Wins over --strict. A target's path scope still applies: only the host check is waived --scope-file Bug-bounty scope file: one host pattern per line, ! to exclude, *.example.com for a wildcard (which covers the apex too), # for a comment. Repeatable and unioned; exclusions always win. See "Scope Files" below --meta-first-seen-after Keep URLs whose oldest archived capture is on or after DATE (YYYY/YYYYMM/YYYYMMDD/YYYYMMDDhhmmss) --meta-first-seen-before Keep URLs whose oldest archived capture is on or before DATE --meta-last-seen-after Keep URLs whose newest archived capture is on or after DATE — "still alive as of" --meta-last-seen-before Keep URLs whose newest archived capture is on or before DATE — "dead since" --meta-mime Keep only URLs whose archived MIME type is one of these (comma-separated; image/* matches any subtype) --meta-exclude-mime Drop URLs whose archived MIME type is one of these --meta-status Keep only URLs whose archived status code matches (comma-separated; 20x / 5xx patterns) --meta-exclude-status Drop URLs whose archived status code matches

Network Options: --network-scope <NETWORK_SCOPE> Control which components network settings apply to (all, providers, testers, or providers,testers) [default: all] --proxy Use proxy for HTTP requests (format: http://proxy.example.com:8080) --proxy-auth <PROXY_AUTH> Proxy authentication credentials (format: username:password) --insecure Skip SSL certificate verification (accept self-signed certs) --random-agent Use a random User-Agent for HTTP requests -H, --header <NAME: VALUE> Extra request header, repeatable; sent only on requests urx makes to the target, never to an archive --cookie Cookie header for requests to the target; shorthand for -H "Cookie: ..." --user-agent User-Agent for requests to the target, overriding the default and --random-agent --timeout Request timeout in seconds [default: 120] --retries Number of retries for failed requests [default: 2] --parallel Maximum domains fetched concurrently per provider (and concurrent URL tests); a provider's --rate-limit is shared across them [default: 5] --rate-limit <RATE_LIMIT> Rate limit (requests per second) --rate-limit-by Per-provider rate overrides (e.g. vt=1,wayback=10); falls back to --rate-limit for unlisted providers --max-time <MAX_TIME> Global ceiling on provider enumeration time in seconds (0 = unlimited) [default: 0]

Testing Options: --check-status Check HTTP status code of collected URLs [aliases: ----cs] --check-title Also record each response's HTML while checking statuses; implies --check-status --include-status <INCLUDE_STATUS> Include URLs with specific HTTP status codes or patterns (e.g., --is=200,30x) [aliases: ----is] --exclude-status <EXCLUDE_STATUS> Exclude URLs with specific HTTP status codes or patterns (e.g., --es=404,50x,5xx) [aliases: ----es] --extract-links Extract additional links from collected URLs (requires HTTP requests) --extract-js-endpoints Fetch collected JavaScript files and extract the endpoint paths and URLs found in their string literals (requires HTTP requests); with --archive-body this also mines the archived copy of each script --max-js-files Maximum number of files --extract-js-endpoints will fetch (0 = unlimited) [default: 500] --archive-body Fetch the archived body of each collected URL from the Wayback Machine and extract the links inside it (works for pages that no longer exist) --archive-body-limit Maximum number of archived bodies --archive-body fetches per run; bounds distinct bodies, not URLs [default: 500] --archive-body-dir

Keep every body --archive-body replays in DIR, with an index.jsonl mapping each file back to its URL, capture and content type --expand-specs Fetch the API specification documents among the collected URLs (OpenAPI, Swagger, GraphQL introspection; JSON or YAML) and expand every route they document into a URL. See "Expanding API Specifications" below --max-spec-files Maximum number of specification documents --expand-specs will fetch (0 = unlimited) [default: 50]

Cache Options: --incremental Enable incremental scanning mode (only return new URLs compared to previous scans) --cache-type Cache backend: sqlite or redis [default: sqlite] --cache-path Path for the SQLite cache database --redis-url Redis connection URL for remote caching --cache-ttl Cache time-to-live in seconds [default: 86400] --no-cache Disable caching entirely

Notification Options: --notify POST a run summary to this webhook when the run ends (repeatable; also URX_NOTIFY_URL, provider-config notify_url, or [notify].url) --notify-on <NOTIFY_ON> When to send: new (only if URLs were emitted), always, or never [default: new] --notify-format <NOTIFY_FORMAT> Payload shape: json (urx summary), slack ({"text"}), or discord ({"content"}) [default: json]

root@kitploit:~
`--extract-links` читает каждый тег, содержащий URL, а не только якоря: `<a href>`,
`<script src>`, `<link href>`, `<form action>`, ``, ``,
`<source src>`, `<object data>`, `<embed src>` и цели
`<meta http-equiv="refresh">`. Относительные URL разрешаются относительно страницы (с учётом `<base href>`),
дубликаты схлопываются, а обнаруженные ссылки проходят через те же фильтры
и проверку хоста, что и остальная часть запуска. Полную таблицу см. в
[docs/content/guide/cli-options.md](https://github.com/hahwul/urx/blob/main/docs/content/guide/cli-options.md).

`--extract-js-endpoints` идёт на шаг дальше и читает сам JavaScript:
каждый собранный URL, похожий на скрипт, загружается, и его
строковые литералы анализируются на предмет путей и URL, которые вызывает приложение —
`fetch("/api/v2/users")`, `axios.post("/graphql")`, статический префикс
`` `/api/orders/${id}` ``. Это эндпоинты, которые никогда не появляются в HTML.
Вывод агрессивно очищается от шума (MIME-типы, спецификаторы модулей, base64,
значения CSS, фрагменты регулярных выражений и многое другое отбрасываются), каждое тело ограничено
10 MiB, количество загружаемых файлов ограничено `--max-js-files`, а
обнаруженные эндпоинты проходят те же фильтры и проверку хоста, что и всё
остальное. Полная политика извлечения и подавления шума приведена в
[docs/content/guide/cli-options.md](https://github.com/hahwul/urx/blob/main/docs/content/guide/cli-options.md#javascript-endpoint-extraction).

`--archive-body` выполняет ту же извлекающую обработку над телами, которые Wayback Machine
*сохранила*, а не над живым сайтом, поэтому страница, удалённая годы назад,
всё ещё выдаёт содержавшиеся в ней ссылки. См.
[Mining Archived Response Bodies](#mining-archived-response-bodies).

### Примеры```bash
# Save results to a file
urx example.com -o results.txt

# Output in JSON format
urx example.com -f json -o results.json

# Filter for JavaScript files only
urx example.com -e js

# Exclude HTML and text files
urx example.com --exclude-extensions html,txt

# Filter for API endpoints
urx example.com --patterns api,v1,graphql

# Exclude specific patterns
urx example.com --exclude-patterns static,images

# Use Fileter Preset (similar to --exclude-extensions=png,jpg,.....)
urx example.com -p no-images

# Use specific providers
urx example.com --providers wayback,otx

# Add the keyless Arquivo.pt (Portuguese web archive) provider
urx example.com --providers wayback,cc,otx,arquivo

# Query another CDX index server alongside the defaults (id: cdx:vefsafn.is)
urx example.is --cdx-endpoint https://vefsafn.is/cdx

# ...or on its own, rate-limited, with the archive-side filters it shares with wayback/cc
urx example.is --cdx-endpoint https://vefsafn.is/cdx --providers cdx:vefsafn.is \
  --rate-limit-by cdx:vefsafn.is=1 --from 2020 --archive-status 200

# URLScan works without a key (anonymous, rate-limited); a key just raises limits
urx example.com --providers urlscan

# BeVigil: endpoints pulled out of unpacked Android apps (key required; auto-enables the provider)
URX_BEVIGIL_API_KEY=*** urx example.com

# Using VirusTotal and URLScan providers
# 1. Explicitly add to providers (with API keys via command line)
urx example.com --providers=vt,urlscan --vt-api-key=*** --urlscan-api-key=***

# 2. Using environment variables for API keys
URX_VT_API_KEY=*** URX_URLSCAN_API_KEY=*** urx example.com --providers=vt,urlscan

# 3. Auto-enabling: providers are automatically added when API keys are provided
urx example.com --vt-api-key=*** --urlscan-api-key=*** # No need to specify in --providers

# 4. Multiple API key rotation (to mitigate rate limits)
# Using repeated flags for multiple keys
urx example.com --vt-api-key=key1 --vt-api-key=key2 --vt-api-key=key3

# Using environment variables with comma-separated keys
URX_VT_API_KEY=key1,key2,key3 URX_URLSCAN_API_KEY=ukey1,ukey2 urx example.com

# Combining CLI flags and environment variables (CLI keys are used first)
URX_VT_API_KEY=env_key1,env_key2 urx example.com --vt-api-key=cli_key1 --vt-api-key=cli_key2

# URLs from robots.txt and sitemap.xml are included by default

# Exclude URLs from robots.txt files
urx example.com --exclude-robots

# Exclude URLs from sitemap
urx example.com --exclude-sitemap

# Also read every archived version of robots.txt and sitemap.xml, so paths the
# site once listed and has since removed come back
urx example.com --archived-discovery

# Only the versions captured in a given era
urx example.com --archived-discovery --from 2014 --to 2016 --exclude-sitemap

# Include subdomains
urx example.com --subs

# Check status of collected URLs
urx example.com --check-status

# Read URLs directly from a text file
urx --files urls.txt

# Combine file input with filtering
urx --files urls.txt --patterns api,admin -f json

# Extract additional links from collected URLs
# (anchors, scripts, stylesheets, form actions, iframes, images, media
#  sources, objects, embeds, and meta-refresh targets)
urx example.com --extract-links

# Discovered links go through the same filters as everything else, so this
# keeps only the JavaScript the pages reference
urx example.com --extract-links -e js

# Read the collected JavaScript and pull out the API paths it calls
urx example.com --extract-js-endpoints --patterns api

# Chain them: collect the site's bundles, then mine those for endpoints
urx example.com --extract-links --extract-js-endpoints --max-js-files 100

# Mine the links inside the *archived* bodies instead — dead pages included.
# One request per distinct body; the limit bounds bodies, not URLs
urx example.com --archive-body --archive-body-limit 200 --rate-limit 5

# Network configuration
urx example.com --proxy http://localhost:8080 --timeout 60 --parallel 10 --insecure

# Advanced filtering
urx example.com -e js,php --patterns admin,login --exclude-patterns logout,static --min-length 20

# HTTP Status code based filtering (live requests: urx re-fetches each URL)
urx example.com --include-status 200,30x,405 --exclude-status 20x

# Archive-side filtering (free: the CDX index already knows these)
# Skip everything the archive recorded as a 404 — no extra requests
urx example.com --archive-exclude-status 404

# Only captures the archive served as JSON — finds extensionless API endpoints
urx example.com --archive-mime application/json

# Drop HTML to leave assets and endpoints behind
urx example.com --archive-exclude-mime text/html

# Restrict the crawl window across wayback, cc, arquivo, and any --cdx-endpoint alike
urx example.com --from 2023 --to 2024

# Disable host validation
urx example.com --strict false

# URL normalization and deduplication
# Normalize URLs by sorting query parameters and removing trailing slashes
urx example.com --normalize-url

# Combine normalization with endpoint merging for comprehensive deduplication
urx example.com --normalize-url --merge-endpoint

# URL normalization with file input
urx --files urls.txt --normalize-url

# Collapse /post/1, /post/2, /post/99999 ... into a single representative line
urx example.com --dedup-similar

# Regular-expression filtering (repeat either flag; they are never comma-split)
urx example.com --match-regex '/api/v[0-9]+/'
urx example.com --match-regex '\.php$' --match-regex '\.aspx$'
urx example.com --filter-regex '/(assets|static)/'

# Regexes are case-sensitive; ask for insensitivity explicitly
urx example.com --match-regex '(?i)admin'

# Security presets: match by path shape as well as by extension
urx example.com -p only-secrets   # /.env, /.git/config, id_rsa, *.pem
urx example.com -p only-backup    # *.bak, *.sql, /backup/, index.php~
urx example.com -p only-config    # *.yaml, web.config, .htaccess, Dockerfile
urx example.com -p only-api       # /api/, /v1/, /graphql, /swagger, *.wsdl

# Scope files: a bug bounty program's own host list, used verbatim
urx example.com --subs --scope-file scope.txt

# Metadata filters, applied after collection so every provider is covered
urx example.com --providers wayback --meta-last-seen-after 2024 --meta-exclude-mime 'image/*'
urx example.com --providers wayback --meta-mime application/json --meta-status 200

# What parameters does this target take, and where?
urx example.com --params
urx example.com --params-by-endpoint

# One templated URL per parameter signature, straight into a fuzzer
urx example.com --fuzz-placeholder FUZZ | ffuf -w - -u FUZZ

# A target-specific wordlist instead of a URL list
urx example.com --subs -f wordlist -o words.txt

# Open the API specifications the sweep found and expand every route in them
urx example.com -p only-api --expand-specs

# Status checks also keep the response head; --check-title adds the <title>
urx example.com --check-status -f jsonl
urx example.com --check-title --show-meta

# Inspect and maintain the cache
urx cache stats
urx cache drop example.com

Ограничение области запуска путём

Цель может указывать путь, и это означает именно то, что написано: urx example.com/shop собирает часть сайта в разделе /shop.```bash urx example.com/shop urx https://example.com/api/v2 # a pasted URL works too

root@kitploit:~
Это не фильтр, применяемый постфактум. Индекс CDX обрабатывает префиксные запросы
нативно, поэтому urx отправляет `url=example.com/shop*`, и архив никогда не передаёт
остальную часть сайта по сети — на крупной цели это разница
между несколькими сотнями строк и несколькими сотнями тысяч. Провайдеры, которые не могут
выразить путь в своём запросе (OTX, VirusTotal, urlscan, GitHub, BeVigil,
ZoomEye), опрашиваются по хосту, а их ответы сужаются afterwards, как
и результаты запуска `--subs`, где форма `*.host` и префикс пути
не могут быть объединены в одном запросе CDX.

Область означает *на или под* путём: `/shop` и `/shop/cart` входят, `/shopping`
нет. Регистр игнорируется, потому что сервер CDX приводит весь URL к нижнему регистру, когда
строит свой индексный ключ — `example.com/Shop*` и `example.com/shop*` возвращают
одни и те же строки, все в нижнем регистре, поэтому проверка с учётом регистра выбросила бы
всё, что только что вернул архив. Строка запроса или фрагмент в
цели отбрасываются — они сужают запрос, а не область.

> Примечание: раньше urx отбрасывал путь из цели, поэтому
> `urx https://example.com/shop` сканировал весь `example.com`. Теперь он
> сканирует `/shop`. Передайте только хост для старого поведения; запуск, цель которого
> содержит путь, сообщает об этом в stderr.

### Фильтрация по регулярным выражениям

`--patterns` / `--exclude-patterns` — это простые проверки на подстроку: обе стороны
приводятся к нижнему регистру, и каждый метасимвол является литералом. `--match-regex` /
`--filter-regex` — это аналоги для регулярных выражений, и они отличаются тремя способами, которые стоит
запомнить:

| | `--patterns` | `--match-regex` |
|---|---|---|
| Сопоставление | подстрока | полный [синтаксис regex](https://docs.rs/regex/latest/regex/#syntax) |
| Регистр | нечувствителен (обе стороны в нижнем регистре) | **чувствителен** — используйте `(?i)`, чтобы отключить |
| Несколько значений | один флаг через запятую | повторяйте флаг; запятые никогда не разделяются |

Оба флага regex вычисляются по **всей строке URL** в том виде, в каком она собрана
(схема, хост, путь и запрос), поэтому работают и `^https://`, и `\.js$`.
Исключение имеет приоритет: URL, соответствующий `--filter-regex`, отбрасывается, даже если
`--match-regex` также совпал с ним. Некорректное выражение приводит к сбою запуска при
старте, до обращения к какому-либо архиву.

### Файлы области

Область программы bug bounty — это список хостов, и каждая платформа записывает его
одинаково. `--scope-file` принимает этот список дословно, вместо того чтобы заставлять вас
вручную переводить его в анкорированные чередования regex — где ошибка в
анкорировании молча *расширяет* область, а не приводит к сбою.```text
# scope.txt — in scope
*.example.com
api.example.org

# out of scope, even though the wildcard above covers them
!admin.example.com
!*.internal.example.com
  • --no-verify — пропустить проверку TLS-сертификата (не рекомендуется).
  • --timeout — таймаут запроса в секундах (по умолчанию: 10).
  • --user-agent — переопределить заголовок User-Agent.
  • --proxy — направлять запросы через прокси (например, http://127.0.0.1:8080).
  • --header — добавить пользовательский заголовок (можно указывать несколько раз).
  • --cookie — отправить cookies вместе с запросом.
  • --data — отправить данные в теле запроса (для методов POST/PUT).
  • --method — явно указать HTTP-метод.
  • --follow-redirects — следовать перенаправлениям HTTP.
  • --max-redirects — ограничить количество перенаправлений (по умолчанию: 5).
  • --output — сохранить тело ответа в файл.
  • --verbose — включить подробный вывод.
  • --silent — подавить весь вывод, кроме тела ответа.
  • --json — выводить ответ в формате JSON.
  • --raw — выводить необработанный ответ без форматирования.
  • --status — выводить только код состояния HTTP.
  • --headers — выводить только заголовки ответа.
  • --body — выводить только тело ответа.
  • --version — показать информацию о версии и выйти.
  • --help — показать справочное сообщение и выйти.```bash urx example.com --subs --scope-file scope.txt urx --domain-list targets.txt --subs --scope-file scope-a.txt --scope-file scope-b.txt
root@kitploit:~
`*.example.com` соответствует как apex-домену, так и всему под ним (трактовка bug-bounty, что и означает таблица scope платформы); голое имя хоста соответствует ровно этому хосту; одинокий `*` превращает файл в чистый deny-list; исключения всегда побеждают; `#` начинает комментарий. Всё, что urx не может обработать — порт, путь, wildcard в середине — это ошибка при запуске с указанием файла и строки, а не молчаливо расширенный scope. Фильтр применяется ко всем провайдерам и к извлечённым ссылкам, и он сочетается с `--strict`, а не заменяет его, поэтому строка scope `*.example.com` всё ещё требует `--subs`.

### Фильтры метаданных архива

`--from`/`--to` и предикаты `--archive-*` передаются в собственный запрос архива, что делает их бесплатными, а также ограничивает их провайдерами на основе CDX — и два диалекта CDX расходятся настолько сильно, что положительный многозначный список (`--archive-status 200,301`) невыполним на серверах pywb. Восемь фильтров `--meta-*` выполняются *после* сбора, по одному объединённому набору метаданных захвата на URL, поэтому они применяются ко всем провайдерам единообразно.```bash
# Endpoints still being captured recently, with HTML and images out of the way
urx example.com --providers wayback --meta-last-seen-after 2024 --meta-exclude-mime 'text/html,image/*'

# Pages that died: nothing captured since 2019
urx example.com --providers wayback --meta-last-seen-before 2019

# JSON the archive served successfully
urx example.com --providers wayback --meta-mime application/json --meta-status 200

# First archived during 2020 (partial dates pad to the start / end of the period)
urx example.com --providers wayback --meta-first-seen-after 2020 --meta-first-seen-before 2020

URL-адреса без метаданных — от провайдеров без CDX, из входных данных --files, из кэша — разделяются по направлению предиката: положительный предикат не может быть удовлетворён отсутствующим значением, поэтому URL отбрасывается; исключение отбрасывает только то, что положительно совпадает, поэтому URL сохраняется. --verbose сообщает о разделении, а когда отсутствующие метаданные объясняют весь набор результатов, urx сообщает об этом даже без -v, потому что иначе попадание в кэш делает пустой запуск похожим на цель, в которой нечего искать.

Схлопывание почти-дубликатов

Архив с радостью вернёт /post/1 вплоть до /post/99999. Это одна конечная точка, и --dedup-similar выводит для них одну строку. Сегмент пути рассматривается как данные — а не как часть маршрута — когда он целиком является одним из:

  • последовательностью цифр (/post/1, /page/42)
  • UUID (/u/550e8400-e29b-41d4-a716-446655440000)
  • 32/40/64-символьным hex-дайджестом (md5, sha1, sha256)
  • датой с разделителями (/blog/2024-01-02/)
  • длинным токеном со смешанным регистром, содержащим цифры (идентификаторы сессий, подписанные блобы)

Сегменты, которые лишь содержат цифры, остаются на месте, поэтому /api/v1/ и /api/v2/ — по-прежнему две конечные точки, а slug в нижнем регистре — это проза, а не токен. Строки запроса группируются только по именам параметров: ?q=cats&page=1 и ?q=dogs&page=7 схлопываются, тогда как ?q=cats в одиночку — нет, поскольку удаление параметра меняет запрос.

Выживший в каждой группе — это лексикографически наименьший URL, поэтому два запуска по одним и тем же данным выводят одно и то же. --verbose сообщает, сколько URL было схлопнуто. Эта опция не зависит от --normalize-url и --merge-endpoint и сочетается с любой из них; всем трём нужен полный набор результатов, поэтому ни одна из них не работает с --stream.

Представления параметров и фаззинга

--show-only-param лишь отрезает строку запроса от каждого URL, что не может ответить на первый вопрос, который задаёт тестировщик: какие параметры принимает эта цель? На него отвечают три представления, построенные на той же группировке, которую использует --dedup-similar.```console $ urx example.com --params page q ref sort utm_source

$ urx example.com --params-by-endpoint https://example.com/post/{id} ref,utm_source https://example.com/search page,q,sort

$ urx example.com --fuzz-placeholder FUZZ https://example.com/post/1?ref=FUZZ https://example.com/post/2?utm_source=FUZZ https://example.com/search?q=FUZZ&page=FUZZ https://example.com/search?q=FUZZ&sort=FUZZ

root@kitploit:~
`--params-by-endpoint` сворачивает сегменты пути, похожие на id, в `{id}` точно так же, как это делает `--dedup-similar`, и выводит endpoint полностью, поскольку urx обычно сканирует несколько хостов за один запуск. `--fuzz-placeholder` сохраняет один URL на сигнатуру параметра и оставляет его реальный путь — `{id}` не привёл бы к маршруту — поэтому вывод можно напрямую подавать в фаззер:```bash
urx example.com --fuzz-placeholder FUZZ | ffuf -w - -u FUZZ
urx example.com --fuzz-placeholder FUZZ | dalfox pipe

Все три требуют полного набора результатов, поэтому они работают только пакетно и взаимно исключают друг друга, а также исключают представления --show-only-*.

Вывод списка слов

-f wordlist превращает запуск в целевой список слов: каждый сегмент пути и имя параметра запроса, которые он встретил, дедуплицированные по всему запуску и отсортированные, по одному термину на строку.```bash urx example.com --subs -f wordlist -o words.txt ffuf -w words.txt -u https://example.com/FUZZ

root@kitploit:~
Сегменты, которые выглядят как данные, а не как имена маршрутов, опускаются, повторно используя
группы теста `--dedup-similar` — список слов, полный `4711`, UUID, дат и
сессионных токенов, хуже, чем отсутствие списка слов, поскольку каждое из этих слов существует
ровно на одной цели. Сегмент, чья основа является идентификатором, также опускается
(`article-1234.html`). Регистр сохраняется: сегменты пути чувствительны к регистру на
большинстве источников, поэтому приведение `WebResource.axd` к нижнему регистру создало бы слово, которое выдаёт 404
везде, где бы оно ни использовалось. Объединение должно быть взято по полному набору, поэтому
формат только пакетный.

### Потоковый вывод

По умолчанию urx собирает всё, затем фильтрует, сортирует и выводит один раз. На
большой цели это означает отсутствие вывода до тех пор, пока не завершится самый медленный архив.
`--stream` записывает каждый URL в момент, когда провайдер, сообщивший о нём, возвращается:```bash
# Matches start appearing immediately instead of after the slowest provider
urx big-target.com --stream | grep admin

# Line-delimited JSON stays valid while it is still being written
urx big-target.com --stream -f jsonl | jq -r 'select(.url | test("/api/")) | .url'

Потоковые URL проходят ровно те же фильтры, что и пакетный запуск, и всё так же дедуплицируются. Отличаются две вещи:

  • Порядок. Результаты приходят в порядке завершения провайдеров, поэтому вывод не отсортирован. Пропустите через sort, если нужен порядок.
  • Область применения. Опции, которым нужен полный набор результатов, отклоняются сразу (с сообщением, называющим каждую из них): --merge-endpoint, --dedup-similar, --check-status / --include-status / --exclude-status, --extract-links, --extract-js-endpoints, --archive-body, --expand-specs, --incremental, --show-sources, --show-meta, фильтры --meta-*, --params, --params-by-endpoint, --fuzz-placeholder, --output-dir и --files. Кэширование обходится; --format json отклоняется в пользу jsonl, потому что массив JSON должен знать, какая запись последняя, а --format wordlist — потому что ни один термин не может считаться новым, пока не пришли все URL.

Поскольку карта результатов пакетного режима в этом режиме никогда не заполняется, потоковый запуск также занимает гораздо меньше памяти — только набор дедупликации уже записанных URL.

Метаданные захвата архива

Индекс CDX записывает больше, чем URL: каждый захват несёт метку времени, MIME-тип и HTTP-статус, которые увидел архив, и дайджест тела. urx сохраняет всё это, поэтому провайдеры на основе CDX — wayback, cc, arquivo и любой --cdx-endpoint — сообщают каждый URL вместе с:

ПолеЗначение
first_seenМетка времени самого старого захвата, 14-значная форма CDX (YYYYMMDDhhmmss)
last_seenМетка времени самого нового захвата
mimeMIME-тип самого последнего захвата, в котором он был записан
archive_statusHTTP-статус, который архив записал во время захвата
digestРепрезентативный дайджест содержимого по всем захватам

archive_status — это не status: status появляется только при --check-status, который заново запрашивает URL в реальном времени, тогда как archive_status — это то, что получил краулер при захвате страницы. URL вполне может иметь archive_status 200 и быть мёртвым сегодня.

Когда один и тот же URL приходит из нескольких захватов или нескольких архивов, значения объединяются: first_seen — самая старая метка времени из всех сообщённых, last_seen — самая новая, а mime/archive_status берутся из самого последнего захвата, в котором они были. Провайдеры без индекса захватов (otx, vt, urlscan, zoomeye, github, bevigil, robots, sitemap и вход --files) сообщают только URL — никакие значения для них не выдумываются.

То, как метаданные отображаются, зависит от формата:

  • json / jsonl — каждое поле появляется как ключ, когда у него есть значение, и полностью опускается, когда его нет, точно так же, как sources.
  • csv — столбец добавляется только тогда, когда хотя бы одна строка имеет для него значение, поэтому запуск без метаданных всё равно даёт единственный столбец url.
  • простой текст — по умолчанию без изменений, один голый URL на строку, так что существующие конвейеры продолжают работать. Передайте --show-meta, чтобы добавить поля.```bash

Rich records: when the URL was alive, and what it served

urx example.com --providers wayback -f jsonl

{"url":"https://example.com/old.php","first_seen":"20040112093000",

"last_seen":"20180722140311","mime":"text/html","archive_status":"200",

"digest":"HT2DYGA5UKZCPBSFVCV3JOBXGW2G5UUA"}

Triage by age: everything last captured before 2010

urx example.com -f jsonl | jq -r 'select(.last_seen < "20100101000000") | .url'

Opt plain output into the metadata

urx example.com --providers wayback --show-meta

root@kitploit:~
Потоковая передача (`--stream`) сообщает только URL-адреса. URL-адрес выводится при первом обнаружении, до того как поступят захваты, которые расширили бы его диапазон `first_seen`/`last_seen`, поэтому `--show-meta` отклоняется там по той же причине, что и `--show-sources`.

Попадание в кэш также не несёт метаданных: кэш хранит URL-адреса, поэтому домен, обслуженный из кэша, сообщает свои URL-адреса без полей захвата. Используйте `--no-cache` (или дождитесь истечения TTL) для запуска, который их перезаполнит.

### Метаданные живого ответа

`--check-status` уже отправляет запрос и ожидает заголовок ответа, поэтому то, что несёт этот заголовок, достаётся бесплатно: `Location`, `Content-Length` и `Content-Type` записываются вместе с кодом состояния. Перенаправления по-прежнему никогда не отслеживаются, поэтому сообщаемый статус всегда принадлежит запрошенному URL-адресу, а `location` просто указывает, куда вёл 3xx.

`--check-title` добавляет HTML `<title>`. Это единственное поле, которое не бесплатно — для заголовка нужно тело ответа — поэтому оно находится за собственным флагом. Чтение ограничено дважды (не более 64 КиБ, и оно останавливается на закрывающем теге) и полностью пропускается для тела, которое сервер объявил как не-HTML, поэтому JSON API или изображение ничего не стоят. Заголовок сжимается по пробелам, декодируется сущности и обрезается до 200 символов. `--check-title` подразумевает `--check-status`.```bash
urx example.com --check-status -f jsonl
urx example.com --check-title --show-meta
urx example.com --check-status --is 30x -f jsonl | jq -r '.url + " -> " + .location'

Правило раскрытия следует тому, что уже задано метаданными архива: json/jsonl/csv всегда содержат поля (отсутствующие ключи опускаются, а столбцы CSV добавляются после существующих), тогда как простой текст остаётся по одному голому URL на строку, если только --show-meta не требует иного. В простом выводе заголовок заключается в кавычки, поскольку это единственное значение, которое регулярно содержит пробелы.

Аутентифицированные и пользовательские запросы

--check-status, --extract-links, --extract-js-endpoints и --expand-specs все повторно запрашивают собранные URL у самой цели. -H предоставляет этим запросам любые необходимые им заголовки:```bash urx example.com --check-status -H "Authorization: Bearer $TOKEN" urx example.com --extract-links --cookie "session=abc; role=admin" urx example.com --check-status --user-agent "acme-security-scan/1.0"

root@kitploit:~
`-H` можно указывать повторно, принимает `Name: value`, и некорректный заголовок останавливает запуск, а не проходит незамеченным — аргумент, который молча отбрасывается, оставляет анонимное сканирование выглядящим как аутентифицированное. `--cookie` и `--user-agent` — это сокращения для соответствующих заголовков.

**Эти заголовки никогда не достигают архива.** Они отправляются только теми компонентами, которые общаются с целью: четырьмя тестерами выше, а также провайдерами `robots` и `sitemap`, которые тоже загружают данные с цели. Все остальные провайдеры запрашивают web.archive.org, index.commoncrawl.org или сторонний API, и то же самое делает `--archive-body`, когда воспроизводит захват; передача им сессионного cookie цели означала бы отправку учётных данных сервису, который сохраняет всё полученное, без какой-либо выгоды. Запросы к архивам сохраняют собственный User-Agent urx, который `--random-agent` по-прежнему ротирует.

### Извлечение тел ответов из архива

`--extract-links` загружает каждый собранный URL с живого сайта, что как раз является неправильным местом для поиска страниц, которые наиболее важны при OSINT-разведке: тех, которых больше не существует. `--archive-body` вместо этого загружает тела, сохранённые Wayback Machine. Для каждого собранного URL, несущего метку времени захвата, urx воспроизводит этот захват в его исходной форме
(`https://web.archive.org/web/<timestamp>id_/<url>` — флаг `id_` отключает панель инструментов Wayback и перезапись ссылок, так что тело представляет собой исходные байты) и запускает по нему то же извлечение ссылок, которое использует `--extract-links`.```bash
# Links from the archived bodies of everything the CDX providers found
urx example.com --archive-body

# Bound the run and pace it; the archive is one host no matter how many URLs
urx example.com --archive-body --archive-body-limit 200 --rate-limit 5

# Only the JavaScript those pages referenced back then
urx example.com --archive-body -e js

Почему для этого требуется гораздо меньше запросов, чем для waymore. Каждая строка CDX содержит дайджест содержимого, и два захвата с одинаковым дайджестом имеют побайтово идентичное тело. Архивы полны таких: каждый вариант ?utm_source= страницы, каждый /index.html рядом с его /, каждая перестановка трекинговых параметров отдаёт идентичные байты, поэтому список из десятков тысяч URL обычно сжимается до нескольких тысяч различных тел. У waymore нет такого понятия — он скачивает один ответ на URL и справляется с объёмом с помощью грубого ограничения -l 5000, которое одновременно нагружает архив и урезает покрытие. urx засчитывает каждый дайджест при первом его появлении и пропускает каждый последующий URL, который воспроизвёл бы те же байты, поэтому то же покрытие стоит одного запроса на различное тело. --archive-body-limit (по умолчанию 500) ограничивает различные тела, а не URL; дубликаты никогда не учитываются в нём, и --verbose сообщает, сколько было пропущено.

Извлечение архивного JavaScript. Поверхность API современного приложения живёт в его бандлах в виде строковых литералов, и --extract-js-endpoints извлекает их с живого сайта — где они часто уже отсутствуют. Бандлы именуются по хешу сборки, поэтому app.a3f9c2.js выдаёт 404 в момент переразвёртывания сайта, и указанные в нём эндпоинты исчезают вместе с ним. Запустите оба флага вместе, и urx извлекает данные из архивной копии вместо этого, а также из встроенных блоков <script> архивной страницы наряду с её ссылками:```bash urx example.com --archive-body --extract-js-endpoints

root@kitploit:~
**Сохранение тел.** Запросы уже выполняются, поэтому запись тел на диск не требует дополнительных затрат и отвечает на вопросы, которые не задаёт ни один извлекатель ссылок: комментарий `<!-- staging.internal -->`, токен, встроенный сборкой 2019 года, трассировка стека с указанием версии фреймворка.```bash
urx example.com --archive-body --archive-body-dir ./corpus
grep -ri "api[_-]key" ./corpus

Каждый файл назван по своему URL плюс хеш от него, а corpus/index.jsonl сопоставляет каждый файл обратно с его URL, временной меткой захвата, дайджестом и типом содержимого. Хранятся только текстовые тела — HTML, script, JSON, XML, CSS, обычный текст — поэтому каталог не заполняется изображениями и шрифтами сайта. Поскольку выборка дедуплицируется по дайджесту, корпус охватывает гораздо больше целевого контента на запрос, чем один ответ на URL.

Детали, которые стоит знать:

  • Подходят только URL с временной меткой захвата. Провайдеры CDX (wayback, cc, arquivo) её предоставляют; вход --files, не-CDX провайдеры и кэшированные результаты (кэш хранит только URL) её не имеют. urx сообщает об этом, когда нечего воспроизводить — передайте --no-cache, чтобы получить свежие захваты.
  • Воспроизводится самый новый захват каждого URL. Временная метка, сообщённая другим архивом, попадает на ближайший захват Wayback; URL, который Wayback Machine никогда не видел, отвечает 404 и пропускается. Захваты, записанные архивом как ошибки, не извлекаются, точно так же как --extract-links игнорирует живые страницы ошибок.
  • Обнаруженные ссылки проходят через те же фильтры, проверку хоста и выходные преобразования, что и всё остальное, и каждое тело ограничено 10 MiB.
  • --rate-limit, --rate-limit-by wayback=N, --parallel, --proxy, --timeout и --retries применяются ко всем запросам воспроизведения.
  • Несовместимо с --stream, как и любая опция, выполняющаяся после сбора.

Расширение спецификаций API

Обход -p only-api находит /swagger.json, /openapi.yaml и /v3/api-docs, а затем никогда их не открывает: --extract-links разбирает HTML, --extract-js-endpoints отбрасывает тела application/json, а --archive-body запускает HTML-парсер по тому, что возвращает архив. --expand-specs читает их и разворачивает каждый маршрут, который они описывают, в результирующий набор — один запрос даёт всю документированную поверхность, точную и уже параметризованную.```bash urx example.com -p only-api --expand-specs urx example.com --expand-specs --max-spec-files 10 --rate-limit 2

Recover an API the live host no longer serves: read the archived document

urx example.com --archive-body --expand-specs

root@kitploit:~
Что разворачивается:

* **OpenAPI 3.x** — `servers[].url` (абсолютный, относительно документа и шаблонный,
  с `{var}`, разрешаемым из `variables[var].default` или первого значения `enum`)
  в сочетании с каждым ключом `paths`; собственные `servers` элемента пути
  переопределяют серверы документа.
* **Swagger 2.0** — `schemes` × `host` + `basePath`, каждая часть откатывается к
  соответствующей части URL самого документа. `ws`/`wss` отбрасываются.
* **Интроспекция GraphQL** — один URL на каждое поле query, mutation и subscription,
  записываемый как эндпоинт плюс `?query=…`. Схема, сохранённая в файл,
  разрешается в свой эндпоинт (`/graphql/schema.json` → `/graphql`).

JSON и YAML читаются оба. Цели выбираются сначала по имени и бесплатно (подстрока
маркера спецификации — `swagger`, `openapi`, `api-docs`, `graphql`,
`introspection` — плюс расширение `json`/`yaml`/`yml`, когда оно есть, так что
`swagger-ui.html` не стоит ни одного запроса), затем по `Content-Type` ответа.
Шаблоны путей выводятся так, как их записывает документ (`/users/{id}`, а не
`/users/%7Bid%7D`). Тела ограничены 10 MiB, а YAML-документ с более
чем 32 ссылками-алиасами отклоняется до разбора, чтобы исключить бомбы
разворачивания. `--max-spec-files` (по умолчанию 50) ограничивает число
загружаемых документов. При также включённом `--archive-body` архивная
спецификация читается как одна без дополнительных затрат на запрос — тело уже
было загружено.

### Архивные robots.txt и sitemap.xml

Провайдеры `robots` и `sitemap` читают *живые* файлы, которые говорят лишь о том,
что сайт скрывает или перечисляет сегодня. `--archived-discovery` также читает
каждую отдельную версию этих файлов, сохранённую Wayback Machine. `Disallow:`
от 2015 года называет пути, о которых сайт с тех пор перестал упоминать — часто
потому, что их хотели забыть, а не потому, что они исчезли, — а старый sitemap
перечисляет всё, что сайт когда-то хотел обойти сканером.```bash
# Every archived version of robots.txt and sitemap.xml, alongside the live ones
urx example.com --archived-discovery

# Bound it and pace it; both archived providers answer to --rate-limit-by
urx example.com --archived-discovery --archived-discovery-limit 20 --rate-limit-by robots=2,sitemap=2

# Only the versions captured in a given era
urx example.com --archived-discovery --from 2014 --to 2016

Как это работает и почему это дёшево:

  • Версии документа перечисляются с помощью одного CDX-запроса на файл (robots.txt, sitemap.xml, sitemap_index.xml, sitemap.txt), используя collapse=digest, чтобы последовательные захваты, отдавшие одинаковые байты, сворачивались в одну строку. Запрашиваются только строки, записанные как успешные: индекс объединяет www. и apex в один список, и их чередующиеся строки 301/200 иначе ломают свёртку — для github.com/robots.txt это 325k строк без фильтра и 14k с ним, при одних и тех же 107 различных версиях.
  • Каждая отдельная версия воспроизводится в сыром виде (/web/<timestamp>id_/…) и передаётся тому же парсеру, что и живой файл. Никакого второго парсера: robots.txt 2015 года читается ровно по тем же правилам, что и текущий, включая проверки абсолютных путей и пропуска шаблонов. Архивный <sitemapindex> прослеживается в его дочерние элементы такими, какими они были в тот же момент.
  • Захваты, записанные архивом как ошибки (robots.txt github.com был 401 часть 2007 года), пропускаются без запроса и сообщаются только при --verbose.
  • --archived-discovery-limit (по умолчанию 50) ограничивает количество документов, загружаемых на домен каждым архивным провайдером, начиная с самых новых версий; вложенные sitemap учитываются. --verbose сообщает, когда лимит обрезал список.
  • Архивные варианты работают как собственные экземпляры провайдеров — "Robots.txt (archived)" и "Sitemap (archived)" в --stats и --show-sources — но под существующими идентификаторами robots / sitemap, поэтому --exclude-robots, --exclude-sitemap и --rate-limit-by robots=N управляют как живыми, так и архивными чтениями. --from / --to сужают, какие версии рассматриваются.
  • Работает с --stream; это провайдер, как и любой другой.

Фильтрация на стороне архива

--archive-status, --archive-mime, --from и --to вычисляются CDX-индексом архива, а не urx. Стоит знать о двух последствиях:

  • Они применяются только к провайдерам на основе CDX — wayback, cc, arquivo и любому --cdx-endpoint. Другие провайдеры их игнорируют; urx предупреждает, когда ни один не включён.
  • Архивы не используют один диалект фильтров. Wayback Machine (и любой endpoint с --cdx-dialect classic) трактует значения как регулярные выражения, поэтому --archive-status "30." соответствует любому 3xx. Common Crawl, Arquivo.pt и pywb-endpoints сопоставляют точно, и их индекс объединяет повторяющиеся фильтры через AND — поэтому много­значный положительный список вроде --archive-status 200,301 там невыполним. urx пропускает этот фильтр для таких провайдеров (с предупреждением) вместо отправки запроса, который вернулся бы пустым. Много­значные исключения означают "не это и не то" и работают везде.

Используйте --archive-status, когда вам нужно то, что архив записал во время сканирования, и --check-status / --include-status, когда вам нужен статус цели сейчас; последние повторно запрашивают каждый URL.

Пользовательские CDX-endpoints

Каждый веб-архив, построенный на pywb, OutbackCDX или CDX-сервере Internet Archive, предоставляет один и тот же API запросов. Вместо жёсткого задания провайдера для каждого архива, --cdx-endpoint URL превращает любой такой сервер в провайдера на месте:```bash

The Icelandic web archive, alongside the default providers

urx example.is --cdx-endpoint https://vefsafn.is/cdx

Several at once; each gets its own progress line, stats row and rate limit

urx example.com --cdx-endpoint https://vefsafn.is/cdx --cdx-endpoint http://localhost:8080/cdx
--rate-limit-by cdx:vefsafn.is=1

root@kitploit:~
* Идентификатор провайдера — `cdx:<host>` (`cdx:vefsafn.is`), именно его используют
  `--exclude-providers`, `--rate-limit-by`, `--stats` и `--show-sources`.
  Указание эндпоинта включает его; запись в `--providers` не требуется, а
  `--providers cdx:vefsafn.is` запускает его отдельно. `--list-providers` показывает
  эндпоинты, указанные в той же командной строке, с идентификаторами, под которыми они будут запущены.
* Всё, что поддерживают встроенные CDX-провайдеры, действует и здесь: `--subs`,
  `--from`/`--to`, фильтры `--archive-*`, пагинация, `--rate-limit` и
  описанные выше метаданные захвата.
* `--cdx-dialect classic|pywb` задаёт диалект сервера (имена полей, семантика фильтров,
  формат строк и схема пагинации следуют из него — см. «Archive-side Filtering»). Если не задан,
  urx один раз за запуск опрашивает эндпоинт и откатывается к `pywb`, более распространённому
  диалекту; задавайте его явно, когда проба не может определить (например, пустой ответ для
  неизвестного домена).
* Также можно задать в файле конфигурации (`cdx_endpoint = [...]`, `cdx_dialect`).

**Проверенные эндпоинты.** На момент написания единственный публичный эндпоинт, подтверждённо
работающий от начала до конца, — `https://vefsafn.is/cdx` (исландский веб-архив
Landsbókasafn, диалект pywb). О нём нужно знать две вещи: он игнорирует `limit`, `page`
и `showNumPages` и возвращает полный набор результатов для каждого запроса, что
urx обрабатывает; и после нескольких запросов он может начать отвечать
страницей бот-защиты в стиле Anubis («Session Verification»). urx обнаруживает HTML-ответ
вместо строк CDX и сообщает о нём как об ошибке провайдера с указанием
эндпоинта — это никогда не засчитывается как «нет URL». Если вы с этим столкнулись, замедлитесь с
`--rate-limit-by cdx:vefsafn.is=1` или повторите попытку позже.

**Известно, что не работает.** UK Web Archive (`webarchive.org.uk`), веб-архив Библиотеки
Конгресса (`webarchive.loc.gov`), Bibliotheca Alexandrina и
Национальная библиотека Австралии (`web.archive.org.au`) — все они находятся за бот-защитой
или перенаправлениями, которые блокируют их CDX API для клиента командной строки.
urx не пытается это обойти, поэтому указание `--cdx-endpoint` на них
даёт ошибку HTML-ответа, описанную выше.

### Кэширование и инкрементальное сканирование

Urx поддерживает кэширование для повышения производительности при повторных сканированиях и инкрементальное сканирование для обнаружения только новых URL.```bash
# Enable caching with SQLite (default)
urx example.com --cache-type sqlite --cache-path ~/.urx/cache.db

# Use Redis for distributed caching
urx example.com --cache-type redis --redis-url redis://localhost:6379

# Incremental scanning - only show new URLs since last scan
urx example.com --incremental

# Set cache TTL (time-to-live) to 12 hours
urx example.com --cache-ttl 43200

# Disable caching entirely
urx example.com --no-cache

# Combine incremental scanning with filters
urx example.com --incremental -e js,php --patterns api

# Configuration file with caching settings
urx -c example/config.toml example.com

Управление кэшем

urx cache проверяет и обслуживает кэш, не трогая базу данных вручную. Каждая подкоманда учитывает те же --cache-type, --cache-path, --redis-url и --cache-ttl, что и сканирование, и все пять работают с обоими бэкендами.```bash urx cache stats # entries, domains, URLs, age span, size, expired count urx cache list # per-domain counts, last scan, TTL remaining urx cache list --domain '*.example.com' urx cache prune # delete only what --cache-ttl has expired urx cache drop example.com # rescan one target without clearing the rest urx cache clear --yes # delete everything

machine-readable

urx cache stats -f json | jq '.expired_entries'

root@kitploit:~
Сопоставление доменов нечувствительно к регистру и **точное**, если только шаблон не содержит
`*` — сопоставление по подстроке по умолчанию позволило бы `drop example.com` удалить
`notexample.com` тоже. `clear` спрашивает перед удалением и отказывается работать с
неинтерактивным stdin, вместо того чтобы предполагать ответ, `drop` называет любой шаблон,
который ничему не соответствовал, просмотр кэша никогда его не создаёт, а Redis очищается
с помощью `SCAN`, а не блокирующей `KEYS` (при этом любой пароль в `--redis-url`
редактируется перед выводом).

#### Сценарии использования кэширования```bash
# Daily monitoring - only alert on new URLs (built-in webhook, see below)
urx target.com --incremental --silent --notify https://hooks.slack.com/services/... --notify-format slack

# ...or hand the new URLs to an external notifier
urx target.com --incremental --silent | notify-tool

# Efficient domain lists processing
cat domains.txt | urx --incremental --cache-ttl 3600 > new_urls.txt

# Distributed team scanning with Redis
urx example.com --cache-type redis --redis-url redis://shared-cache:6379

# Fast re-scans during development
urx test-domain.com --cache-ttl 300  # 5-minute cache for rapid iterations

Уведомления через вебхуки

--notify <URL> отправляет POST-запрос со сводкой о запуске на вебхук по завершении запуска, что превращает --incremental в монитор: поместите его в cron, и вебхук сработает только тогда, когда появится что-то новое.```bash

Slack incoming webhook, only when the run finds new URLs (the default)

urx target.com --incremental --silent
--notify https://hooks.slack.com/services/T000/B000/XXXX --notify-format slack

Discord, and send even when nothing is new

urx target.com --incremental --notify "$DISCORD_HOOK" --notify-format discord --notify-on always

Several receivers, urx's own JSON schema (the default format)

urx target.com --incremental --notify https://n8n.example/hook --notify https://ntfy.example/urx

Keep the webhook out of the shell history

export URX_NOTIFY_URL=https://hooks.slack.com/services/... urx target.com --incremental --notify-format slack

root@kitploit:~
- `--notify-on` по умолчанию имеет значение `new`: ничего не отправляется, когда запуск выдаёт ноль
  URL-адресов, поэтому тихий запуск cron остаётся тихим. `always` отправляет в любом случае; `never`
  сохраняет конфигурацию, но отключает отправку.
- `--notify-format json` (по умолчанию) отправляет схему urx: `domains`,
  `incremental`, `url_count`, `new_url_count`, `elapsed_ms`, список `providers`
  по каждому провайдеру (те же числа, что выводит `--stats`), и `sample` из не более
  чем 20 выданных URL-адресов с установленным `sample_truncated`, когда найдено больше.
  `slack` отправляет `{"text": ...}`, а `discord` отправляет `{"content": ...}` с
  коротким человекочитаемым сообщением; сообщения длиннее, чем допускает сервис,
  обрезаются по границе строки и заканчиваются на `[truncated: N lines cut ...]`.
- Доставка никогда не изменяет код выхода. URL-адреса уже находятся в stdout или в
  `--output` к моменту вызова webhook, поэтому неработающий webhook — это предупреждение
  в stderr, и запуск всё равно завершается с кодом 0. `--verbose` показывает статус ответа.
- URL webhook — это учётные данные. urx никогда не выводит больше, чем его схему и
  хост — ни в `--verbose`, ни в предупреждениях, ни в `--stats`. Чтобы не хранить его
  в конфиге, который попадает в систему контроля версий, поместите его в `URX_NOTIFY_URL` или как
  `notify_url` в файле конфигурации провайдера; `[notify].url` в основном конфиге
  тоже работает. Приоритет: CLI/env > конфигурация провайдера > основной конфиг.
- Запрос учитывает `--proxy`, `--proxy-auth`, `--timeout` и `--insecure`.
  `--network-scope` не применяется: он разделяет трафик, направленный на цель
  и архивы, а webhook — это ваша собственная конечная точка.
- `--silent` всё равно отправляет (это основной вариант использования); он только скрывает
  диагностику.

## Интеграция с другими инструментами

Urx хорошо работает в конвейерах с другими инструментами безопасности и разведки:```bash
# Find domains, then discover URLs
echo "example.com" | urx | grep "login" > potential_targets.txt

# Combine with other tools
cat domains.txt | urx --patterns api | other-tool

Вдохновение

Urx был вдохновлён gau (GetAllUrls) — инструментом, который извлекает известные URL-адреса из AlienVault's Open Threat Exchange, Wayback Machine и Common Crawl. Хотя Urx обладает схожей базовой функциональностью, он был создан с нуля на Rust с упором на производительность, конкурентность и расширенные возможности фильтрации.

Участие в разработке

Urx — это проект с открытым исходным кодом, созданный с ❤️ если вы хотите внести свой вклад в этот проект, пожалуйста, ознакомьтесь с CONTRIBUTING.md и отправьте Pull-Request с вашими интересными материалами.