Перед запуском кампании можно автоматически сверить список IG-аккаунтов с брифом и получить CSV только с записями, требующими внимания. Для каждой строки скрипт запросит профиль, сравнит username, статус приватности и верификацию с ожидаемыми значениями, а также сохранит доступные счётчики. Это превращает повторяющуюся ручную проверку в понятный контрольный шаг перед передачей кампании в работу.
Задача: найти расхождения до публикации
В таблице кампании обычно есть имя аккаунта и несколько ожиданий: профиль должен быть публичным, username должен соответствовать согласованному, а отметка верификации — совпадать с записью в брифе. Между подготовкой списка и запуском аккаунт может сменить имя, стать приватным или оказаться другим профилем с похожим названием. Если проверять строки вручную, сложно повторить процесс и быстро выделить исключения.

Для такой предварительной диагностики достаточно получать профиль по username. В опубликованной документации jsonscraper указан маршрут GET /v1/user/by/username с параметром username; также доступен необязательный cache_timeout. В ответе могут присутствовать username, полное имя, признаки private и verified, число публикаций, подписчиков и подписок, а также биография. Конкретные поля нужно читать из фактического ответа: снимок схемы подтверждает их наличие в наблюдавшемся ответе, но значения могут различаться или отсутствовать.
Подготовьте таблицу и правила проверки
Создайте CSV profiles.csv с колонками username, expected_private и expected_verified. В этих двух колонках укажите ожидаемые значения true или false, а username запишите без символа @. Если для какого-то профиля ожидание неизвестно, оставьте ячейку пустой: скрипт не должен превращать отсутствие ожидания в ошибку.
username,expected_private,expected_verified
examplebrand,false,true
anotheraccount,false,false
Здесь проверка решает две узкие задачи: определяет, совпадает ли полученное имя пользователя с запрошенным, и выявляет отличия от зафиксированных ожиданий о приватности и верификации. Счётчики и биография сохраняются для контекста и ручной оценки, а не трактуются как доказательство качества аудитории или пригодности автора для кампании.
Подключите IG Scraper API
Сохраните ключ доступа в переменной окружения JSONSCRAPER_INSTAGRAM_LICENSE_KEY. Не записывайте секрет в CSV, исходный код или журналы запуска. Официальная справка по endpoint IG описывает маршрут и имена параметров; базовый адрес API — https://ig.jsonscraper.com, а имя параметра для ключа — license_key.
Перед обработкой полного списка сделайте один пробный вызов для тестовой строки, проверьте структуру JSON и убедитесь, что ваш аккаунт имеет доступ. Поскольку endpoint принимает username, известный идентификатор профиля и дополнительные маршруты для этого простого сценария не требуются.
Пример: запросы, сравнение и CSV с исключениями
Следующий скрипт совместим с Python 3.8+. Он читает CSV, выполняет по одному GET-запросу на профиль, проверяет внешний статус ответа и сохраняет исходные значимые поля вместе с результатом сравнения. Установите зависимость командой python -m pip install requests, затем экспортируйте ключ перед запуском.

import csv
import os
import time
from pathlib import Path
import requests
BASE_URL = "https://ig.jsonscraper.com/v1/user/by/username"
API_KEY = os.environ["JSONSCRAPER_INSTAGRAM_LICENSE_KEY"]
INPUT_FILE = Path("profiles.csv")
OUTPUT_FILE = Path("preflight_results.csv")
def parse_expected(value):
value = (value or "").strip().lower()
if value == "true":
return True
if value == "false":
return False
return None
def profile_from_response(payload):
# The documented observed response wraps profile fields in "ig".
if payload.get("status") != "ok":
raise ValueError("API response status is not ok")
profile = payload.get("ig")
if not isinstance(profile, dict):
raise ValueError("Response has no profile object under 'ig'")
return profile
with INPUT_FILE.open(newline="", encoding="utf-8") as source:
rows = list(csv.DictReader(source))
results = []
for row in rows:
requested = (row.get("username") or "").strip().lstrip("@")
if not requested:
results.append({
"requested_username": "",
"result": "missing_username",
"error": "username is empty",
})
continue
try:
response = requests.get(
BASE_URL,
params={"username": requested, "license_key": API_KEY},
timeout=30,
)
response.raise_for_status()
profile = profile_from_response(response.json())
actual_username = profile.get("username")
actual_private = profile.get("is_private")
actual_verified = profile.get("is_verified")
expected_private = parse_expected(row.get("expected_private"))
expected_verified = parse_expected(row.get("expected_verified"))
checks = []
if actual_username and actual_username.casefold() != requested.casefold():
checks.append("username_mismatch")
if expected_private is not None and actual_private != expected_private:
checks.append("privacy_mismatch")
if expected_verified is not None and actual_verified != expected_verified:
checks.append("verification_mismatch")
results.append({
"requested_username": requested,
"username": actual_username,
"full_name": profile.get("full_name"),
"is_private": actual_private,
"is_verified": actual_verified,
"media_count": profile.get("media_count"),
"follower_count": profile.get("follower_count"),
"following_count": profile.get("following_count"),
"result": "review" if checks else "matched",
"checks": ";".join(checks),
"error": "",
})
except (requests.RequestException, ValueError, KeyError) as exc:
results.append({
"requested_username": requested,
"result": "request_or_response_error",
"error": str(exc),
})
# A small delay spaces requests; it is not a documented quota guarantee.
time.sleep(0.5)
fieldnames = sorted({key for item in results for key in item})
with OUTPUT_FILE.open("w", newline="", encoding="utf-8") as destination:
writer = csv.DictWriter(destination, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(results)
print("Saved", len(results), "rows to", OUTPUT_FILE)
В коде проверяется именно наблюдавшаяся обёртка ответа: внешний status и объект профиля ig. Если поставщик изменит формат, проверка структуры остановит обработку конкретной записи и сохранит ошибку, вместо того чтобы молча создать неверное совпадение. Скрипт не печатает ключ и не помещает его в итоговый файл.
Как читать результат
В preflight_results.csv строки со статусом matched прошли заданные сравнения. Значение review означает, что один или несколько параметров отличаются от брифа; колонка checks показывает, какие именно. Ошибка запроса или ответа отмечается отдельно, поэтому недоступность данных не выглядит как подтверждённое совпадение.
Число подписчиков и публикаций помогает человеку увидеть текущий снимок профиля рядом с заявкой. Это моментальные значения из ответа на запрос. Для оценки изменений во времени сохраняйте отдельные датированные запуски; одна проверка не содержит истории. Поля могут быть пустыми, и тогда запись остаётся пригодной для проверки идентичности и остальных доступных признаков, но не для сравнения отсутствующего счётчика.
Автоматизация перед запуском кампании
После ручной проверки тестового CSV добавьте скрипт в расписание или шаг подготовки кампании. Для воспроизводимого контроля храните исходный список отдельно, записывайте дату запуска и сохраняйте CSV результатов в закрытом рабочем хранилище. Для повторной обработки удобно использовать стабильный идентификатор строки из вашей системы, если username может меняться.
При росте списка добавьте ограничение параллельности, повторные попытки только для временных сетевых ошибок и отдельный журнал кодов ошибок без секретов. Не запускайте бесконечные повторы для неверного ключа или некорректного username. Значение cache_timeout можно добавить только согласно нужной политике свежести: документация указывает, что для IG кэширование отключено по умолчанию, а значение больше нуля включает кэш на заданный период.
Проверка профиля сокращает ручную сверку до конкретного списка исключений: имя, публичность, верификация и доступные счётчики оказываются в одной таблице до старта кампании. Для параметров API и актуальных вариантов интеграции используйте страницу IG Scraper API и документацию маршрутов.