Русский · English
Готовые примеры работы с API проверки SSL/TLS-сертификата на шести языках: Python, TypeScript (Node.js), Go, Java, C#, PHP.
Узнать, когда истекает сертификат домена, кто его выдал, какие имена он покрывает (SAN), какая версия TLS на порту и цела ли цепочка доверия. Мониторинг SSL-сертификатов и проверка сертификата из Python — одним HTTP-запросом, без openssl s_client и без своего TLS-хендшейка.
Каждый пример запускается сразу — без регистрации, без ключа, без карты. В коде зашит публичный демо-ключ.
git clone https://github.com/atlorium-api/ssl-certificate-check-api-client
cd ssl-certificate-check-api-client/python && pip install -r requirements.txt && python main.pyДемо-ключ: сертификат сгенерирован (мок), а не снят с реального хоста.
Проверено хостов: 1 — запросов к API: 1
ХОСТ ДНЕЙ ИСТЕКАЕТ TLS ИЗДАТЕЛЬ СТАТУС
atlorium.com 321 2027-05-31 Tls13 Let's Encrypt OK
Вердикт: OK — все сертификаты валидны, запас больше 30 дн.
Код выхода: 0
Демо-ключ отдаёт моки. Сертификат в выводе выше сгенерирован сервером песочницы, а не снят с настоящего
atlorium.com: даты, серийный номер и отпечаток правдоподобны, но это не тот сертификат, который отдаёт живой хост. Подставьте боевой ключ — тот же код начнёт делать настоящий TLS-хендшейк и покажет реальные данные. Мониторинг имеет смысл только с боевым ключом; демо-ключ нужен, чтобы написать и протестировать интеграцию до оплаты.
Это не «печаталка JSON», а готовая проверка для cron и CI. Программа сама решает, всё ли в порядке, и сообщает об этом кодом выхода — парсить её вывод не нужно:
| Код выхода | Когда |
|---|---|
0 |
OK — все сертификаты валидны, до истечения больше 30 дней |
1 |
WARNING — до истечения меньше 30 дней: пора продлевать |
2 |
CRITICAL — меньше 7 дней, сертификат невалиден, самоподписан, битая цепочка или хост не покрыт SAN |
3 |
Проверку выполнить не удалось: ошибка API или сети |
Поэтому шаг в GitHub Actions пишется в одну строку — он покраснеет сам:
name: ssl-expiry
on:
schedule:
- cron: '0 7 * * *' # каждое утро
workflow_dispatch:
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: '3.12' }
- run: pip install -r requirements.txt
working-directory: python
# Ненулевой код выхода = красный джоб = уведомление на почту.
# Никакого grep по выводу, никаких внешних сервисов мониторинга.
- run: python main.py example.com api.example.com www.example.com
working-directory: python
env:
ATLORIUM_API_KEY: ${{ secrets.ATLORIUM_API_KEY }}Ровно так же он ставится в cron — cron пришлёт письмо, если команда завершилась ненулевым кодом:
0 7 * * * cd /opt/ssl-check/python && python main.py example.com api.example.comЕсли передать больше одного хоста, примеры используют пакетный эндпоинт /api/Certificate/batch. До 10 хостов проверяются за один вызов — это один запрос по тарификации и один по rate-limit вместо десяти, а сервер проверяет хосты параллельно:
python main.py atlorium.com github.com api.stripe.comДемо-ключ: сертификат сгенерирован (мок), а не снят с реального хоста.
Проверено хостов: 3 — запросов к API: 1
ХОСТ ДНЕЙ ИСТЕКАЕТ TLS ИЗДАТЕЛЬ СТАТУС
atlorium.com 321 2027-05-31 Tls13 Let's Encrypt OK
github.com 53 2026-09-05 Tls13 Let's Encrypt OK
api.stripe.com 201 2027-01-31 Tls13 Let's Encrypt OK
Вердикт: OK — все сертификаты валидны, запас больше 30 дн.
Код выхода: 0
Один прогон примера — ровно один запрос к API, сколько бы хостов вы ни передали (до 10).
Просроченный сертификат — это авария, которую видно всем: браузер закрывает сайт красным экраном, мобильное приложение перестаёт ходить в API, платёжный вебхук молча перестаёт доставляться. При этом ошибка предсказуема за месяцы вперёд — её достаточно один раз поставить на мониторинг.
Примеры не просто печатают JSON, а применяют данные: в каждом есть функция monitorExpiry(), которая выносит вердикт:
- Светофор по сроку.
daysRemaining < 7— CRITICAL,< 30— WARNING. (Сертификаты Let's Encrypt живут 90 дней, поэтому 30/7 — рабочие пороги.) - Валидность и цепочка.
isValid, содержимоеerrors[]и ошибки вcertificateChain[]: истёкший, самоподписанный, отозванный, выданный неизвестным УЦ. - Несовпадение SAN. Запрошенный хост сверяется с
subjectAlternativeNames— с учётом wildcard-масок вида*.example.com. Это отдельная, коварная авария: сертификат может быть идеально валиден, но выписан на другое имя, и браузер всё равно покажетNET::ERR_CERT_COMMON_NAME_INVALID. Классика — сертификат на*.example.comповесили на голыйexample.com: маска покрывает ровно один уровень поддомена и сам домен не покрывает.
Проверить API вообще без клонирования:
curl -H "Authorization: Bearer ak_sandbox_demo_mockdata_v1" \
"https://atlorium.com/api/Certificate?host=atlorium.com"| Язык | Запуск | Требуется |
|---|---|---|
| Python | pip install -r requirements.txt && python main.py |
Python 3.10+ |
| TypeScript / Node.js | npm install && npm start |
Node.js 20+ |
| Go | go run . |
Go 1.22+ |
| Java | java Main.java |
JDK 11+ (без зависимостей) |
| C# | dotnet run |
.NET 8+ |
| PHP | php main.php |
PHP 8.1+ |
Передать свои хосты аргументом: python main.py example.com api.example.com
Ключ передаётся в заголовке Authorization:
Authorization: Bearer ВАШ_КЛЮЧ
| Ключ | Что делает |
|---|---|
ak_sandbox_demo_mockdata_v1 |
Демо-ключ. Публичный, один на всех. Возвращает моки, денег не списывает, регистрации не требует. Ответы детерминированы: один и тот же хост всегда даёт один и тот же результат — на них можно писать стабильные тесты. |
| Боевой ключ | Настоящий TLS-хендшейк с указанным хостом. Получить в личном кабинете: atlorium.com |
Переход на боевой ключ не требует правок в коде — все примеры читают переменную окружения:
export ATLORIUM_API_KEY="ak_ваш_боевой_ключ"Каждый ответ песочницы помечен заголовком X-Atlorium-Sandbox: true — перепутать мок с реальными данными невозможно.
Базовый адрес: https://atlorium.com
| Метод | Путь | Назначение |
|---|---|---|
GET |
/api/Certificate |
Сертификат одного хоста |
GET |
/api/Certificate/url |
Сертификат по URL — хост и порт извлекаются автоматически |
GET |
/api/Certificate/batch |
Пакетная проверка до 10 хостов за один запрос |
| Параметр | Где | Тип | Описание |
|---|---|---|---|
host |
query | string | Доменное имя или IP: example.com, www.example.com, 192.168.1.1 |
port |
query | int | Порт, по умолчанию 443. Диапазон 1–65535. Полезно для почты: 993 (IMAPS), 995 (POP3S), 465 (SMTPS), 8443 (альтернативный HTTPS) |
| Параметр | Где | Тип | Описание |
|---|---|---|---|
url |
query | string | Полный URL: https://example.com, https://example.com:8443/api/v1. Хост и порт извлекаются сами. Удобно, когда URL скопировали из браузера |
| Параметр | Где | Тип | Описание |
|---|---|---|---|
hosts |
query | string | Хосты через запятую: a.com,b.com,c.com. Максимум 10 за запрос, пробелы вокруг запятых допустимы |
port |
query | int | Один порт для всех хостов списка, по умолчанию 443. Нужны разные порты — делайте отдельные запросы |
| Поле | Тип | Что содержит |
|---|---|---|
isValid |
bool | Ключевое поле. Прошёл ли сертификат валидацию целиком |
daysRemaining |
int | Дней до истечения. То, ради чего обычно и зовут этот API |
expirationDate |
datetime | Дата и время истечения (UTC) |
validFrom |
datetime | С какого момента сертификат действителен |
issuer |
string | Издатель в формате DN: CN=R3, O=Let's Encrypt, C=US |
subject |
string | Субъект в формате DN: CN=example.com |
subjectAlternativeNames |
array | SAN — имена, которые покрывает сертификат. Именно их сверяет браузер, а не CN. Могут содержать wildcard: *.example.com |
errors |
array | Причины невалидности: истёк, неизвестный УЦ, несовпадение имени, отозван |
tlsVersion |
string | Версия TLS соединения: Tls13, Tls12 |
serialNumber |
string | Серийный номер |
thumbprint |
string | Отпечаток сертификата |
signatureAlgorithm |
string | Алгоритм подписи, например sha256RSA |
publicKeyAlgorithm |
string | Алгоритм ключа: RSA, ECDSA |
keySize |
int | Длина ключа в битах, например 2048 |
isSelfSigned |
bool | Самоподписанный — публичные клиенты такой не примут |
hasPrivateKey |
bool | Есть ли приватный ключ (при удалённой проверке всегда false) |
certificateChain |
array | Цепочка доверия: { subject, issuer, validFrom, validTo, thumbprint, isValid, errors } |
connectionTime |
duration | Сколько заняло TLS-соединение |
host / port |
string / int | Что именно проверяли |
checkedAt |
datetime | Момент проверки (UTC) |
Пакетный эндпоинт возвращает массив таких объектов — в том же порядке, в каком перечислены хосты.
| Код | Причина | Что делать |
|---|---|---|
400 |
Хост не указан, порт вне диапазона 1–65535 или в батче больше 10 хостов | Проверьте параметры |
401 |
Ключ отсутствует, просрочен или недействителен | Проверьте заголовок Authorization |
402 |
Недостаточно кредитов на балансе | Пополнить на atlorium.com |
429 |
Превышен rate-limit | Повторить с задержкой — но с потолком ожидания (см. ниже) |
500 |
Не удалось снять сертификат: хост недоступен, таймаут, на порту нет TLS | Проверьте хост и порт. За неудачную проверку деньги не списываются |
Во всех шести примерах коды разложены в человекочитаемые причины — смотрите класс AtloriumError.
Про 429 и потолок ожидания. Исчерпав часовую квоту, сервер честно просит подождать 40+ минут. Клиент, который слепо спит столько, сколько попросили, зависает на всё это время (а в CI съедает бюджет джоба). Поэтому в примерах есть MAX_RETRY_DELAY = 120 секунд: дольше потолка не ждём, а честно сообщаем, что квота исчерпана, и выходим с кодом 3.
Оплата pay-as-you-go, без подписки: платите только за выполненные запросы. Пакетная проверка до 10 хостов тарифицируется как один запрос.
Актуальные цены и лимиты: atlorium.com/pricing
Как узнать, когда истекает сертификат домена? Один GET-запрос — и поле daysRemaining скажет, сколько дней осталось, а expirationDate — точную дату. Именно на этом поле построена функция monitorExpiry() в примерах.
Чем это лучше openssl s_client -connect host:443? Тем, что не нужен ни TLS-стек в вашем коде, ни разбор PEM, ни исходящее соединение с чужим хостом из вашего контура (в закрытом периметре или в serverless-функции его может просто не быть). Ответ приходит готовым JSON, а не текстом для парсинга регулярками.
Что такое несовпадение SAN и почему это важно? Браузер сверяет имя хоста не с CN, а со списком subjectAlternativeNames. Сертификат может быть валиден и не просрочен, но не покрывать нужное имя — и клиенты всё равно получат ошибку. Типичный случай: *.example.com не покрывает сам example.com. Примеры проверяют это явно и выдают MISMATCH.
Можно ли проверять не только 443? Да, параметр port: 993 — IMAPS, 995 — POP3S, 465 — SMTPS, 8443 — альтернативный HTTPS. Сертификаты почтовых серверов протухают ровно так же, а замечают это обычно позже.
Демо-ключ показывает настоящий сертификат моего домена? Нет. Песочница генерирует правдоподобный сертификат: isValid всегда true, errors пуст, SAN всегда содержит запрошенный хост, а daysRemaining попадает в диапазон 30–365. Из-за этого ветки WARNING, CRITICAL и MISMATCH на демо-ключе практически не срабатывают — увидеть их можно только с боевым ключом на реально проблемном хосте. Зато ответы детерминированы, и на них удобно писать тесты.
Есть ли SDK-пакет в PyPI/npm? Пока нет — это самодостаточные примеры без зависимостей, чтобы их можно было скопировать в свой проект целиком.
Мониторинг сертификата — обычно часть более общей задачи «жив ли домен и правильно ли он настроен». Из того же аккаунта и тем же ключом доступны:
- Разбор cron-выражений — валидация расписания и ближайшие запуски с учётом таймзоны
- DNS Lookup — записи домена, MX, SPF, DMARC
- Погодные данные — текущие условия по координатам
- CIDR-калькулятор — разбиение сети на подсети и проверка вхождения IP
- Адреса ГАР/ФИАС — поиск и подсказки по официальному справочнику
- Профиль IP — гео, ASN, детект VPN, прокси и Tor
Полный каталог — atlorium.com
- Документация API (Swagger): atlorium.com/certificateAPI
- Описание сервиса: atlorium.com/certificateDescription
- Веб-интерфейс: atlorium.com/certificateGUI
- OpenAPI-спецификация: certificate_ru.json
- Поддержка: support@atlorium.com
MIT — берите код и используйте как хотите, в том числе в коммерческих проектах.