jsonscraper
Markets
Back to journal

IG: How to Detect Public Profile Issues Before a Campaign Launch

Check profile status, privacy, and basic metrics through an API to turn manual account-list reviews into a reproducible report

Editorial Policy Report an error

Before a campaign launch, you can process a list of IG accounts with a script and get a JSON report containing the API response for each username. The jsonscraper IG Scraper API endpoint returns an external status and a profile object; the observed schema includes the username, privacy and verification indicators, and counts for posts, followers, and following. These fields help identify records for manual review, but do not by themselves explain why a response is missing or unexpected.

Article: IG: How to Detect Public Profile Issues Before a Campaign Launch
Summary: Automatically check IG profiles before a campaign launch: request data through jsonscraper, save the responses, and create a list of accounts that need manual review.
Image role: cover — the central idea
Section: 
Visual subject: Editorial photo of a campaign account checklist beside a phone showing a generic IG profile silhouette, marked verification boxes and a small JSON data card; no re
A preflight check turns a list of usernames into records with API responses and fields that can be reviewed.© jsonscraper · AI-generated

The problem: The account list looks correct, but is it ready to use?

A campaign spreadsheet may include renamed accounts, typos, and private profiles. If the team starts analyzing the list without a preliminary check, someone has to open the accounts one by one. An automated pass reduces manual work and creates a consistent log of exactly what the API returned for each requested username.

The goal of this workflow is limited: process the list, save the actual HTTP responses and JSON, and flag profiles with campaign-relevant indicators for manual review. The report records observed data; it does not determine why a profile was not returned or why a request failed.

What the request checks

The jsonscraper documentation specifies the GET \/v1\/user\/by\/username endpoint. The required parameter is username; the key is passed as license_key. The optional cache_timeout parameter enables caching for a specified number of seconds, while 0 leaves it disabled. The observed successful-response schema contains an outer status and an ig object with profile fields.

For diagnostics, distinguish three facts: whether the HTTP request succeeded; whether the parsed JSON contains an ig object; and which fields are present in that object. If any step does not complete as expected, the script can record a technical result and the original response. That result indicates that a check is needed, but does not establish the cause of the failure.

Prepare the input data and key

Create a usernames.txt file with one username per line, without the @ symbol. Remove blank lines and duplicates, keeping only accounts relevant to the campaign. For later comparison, store the check date and project identifier separately.

Store the key in the JSONSCRAPER_INSTAGRAM_LICENSE_KEY environment variable, not in source code or a repository:

export JSONSCRAPER_INSTAGRAM_LICENSE_KEY="your_key"
python3 check_profiles.py

The example uses the Python 3.8+ standard library and does not require installing HTTP packages.

Example: Request profiles and write a report

The script processes the list one username at a time. For a successful JSON response, it saves the actual body and available profile fields; for an HTTP or network error, it records the technical outcome. Missing fields remain null, and the raw response body is saved if it could be read.

import json
import os
import time
from datetime import datetime, timezone
from urllib.error import HTTPError, URLError
from urllib.parse import urlencode
from urllib.request import Request, urlopen

API_KEY = os.environ.get("JSONSCRAPER_INSTAGRAM_LICENSE_KEY")
if not API_KEY:
    raise SystemExit("Set JSONSCRAPER_INSTAGRAM_LICENSE_KEY")

BASE_URL = "https:\/\/ig.jsonscraper.com\/v1\/user\/by\/username"

with open("usernames.txt", encoding="utf-8") as f:
    usernames = list(dict.fromkeys(
        line.strip().lstrip("@") for line in f if line.strip()
    ))

results = []
for username in usernames:
    params = urlencode({"username": username, "license_key": API_KEY})
    request = Request(f"{BASE_URL}?{params}", method="GET")
    checked_at = datetime.now(timezone.utc).isoformat()

    try:
        with urlopen(request, timeout=30) as response:
            http_status = response.status
            raw_body = response.read().decode("utf-8")
        try:
            payload = json.loads(raw_body)
            json_error = None
        except json.JSONDecodeError as exc:
            payload = None
            json_error = str(exc)

        profile = payload.get("ig") if isinstance(payload, dict) else None
        record = {
            "requested_username": username,
            "checked_at": checked_at,
            "http_status": http_status,
            "api_status": payload.get("status") if isinstance(payload, dict) else None,
            "check_result": "profile_returned" if isinstance(profile, dict) else "unexpected_or_missing_profile_object",
            "response": payload if payload is not None else raw_body,
        }
        if json_error:
            record["json_error"] = json_error
        if isinstance(profile, dict):
            record["returned_username"] = profile.get("username")
            record["is_private"] = profile.get("is_private")
            record["is_verified"] = profile.get("is_verified")
            record["media_count"] = profile.get("media_count")
            record["follower_count"] = profile.get("follower_count")
            record["following_count"] = profile.get("following_count")
        results.append(record)
    except HTTPError as exc:
        body = exc.read().decode("utf-8", errors="replace")
        results.append({
            "requested_username": username,
            "checked_at": checked_at,
            "check_result": "http_error",
            "http_status": exc.code,
            "response": body,
        })
    except (URLError, TimeoutError) as exc:
        results.append({
            "requested_username": username,
            "checked_at": checked_at,
            "check_result": "request_error",
            "detail": str(exc),
        })

    time.sleep(0.5)

with open("profile-check.json", "w", encoding="utf-8") as f:
    json.dump(results, f, ensure_ascii=False, indent=2)

print(f"Results saved: {len(results)}")

This is an integration example, not a report of a test that was performed. The key is passed in the license_key parameter but is not printed. The full response may contain information that should be access-controlled according to your team’s data-retention rules.

How to read the results

A profile_returned record means the script received a JSON ig object. Compare requested_username with returned_username and review the indicators relevant to the campaign workflow. For example, if the campaign requires a public profile, is_private: true can be flagged for manual review.

Article: IG: How to Detect Public Profile Issues Before a Campaign Launch
Summary: Automatically check IG profiles before a campaign launch: request data through jsonscraper, save the responses, and create a list of accounts that need manual review.
Image role: supporting illustration 2 — a different specific aspect
Section: How to read the results
Visual subject: Infographic in Russian: username list → GET IG profile API → HTTP and JSON checks → profile object and username fields
The diagram shows the path from a user list to a report and distinguishes returned profile data from technical errors.© jsonscraper · AI-generated illustration

The http_error, request_error, and unexpected_or_missing_profile_object results indicate only the step at which the script failed to receive the expected structure. They do not prove that an account was deleted, made private, or became unavailable for a specific reason. Save the response, check the username and key, then retry the request or contact the service’s regular support team.

If a field is missing, leave it unknown—do not interpret its absence as zero or false. Profile counts describe the state returned at the time of the request. The timestamp helps distinguish this snapshot from the results of a later run.

Automate without losing observability

Move the run into a task scheduler or an existing ETL workflow. Store the check date, requested username, result, status, and response body. As a separate step, you can load the JSON into a table and send only records that need review to a specialist.

To detect changes, compare snapshots of the same profile using selected fields. A change in the number of posts is a reason to open the profile and check it, not an exact date for when a post appeared. The follower count is also a value from the time of the request, so a history of observations is built from saved snapshots.

For a large list, set a controlled rate, add bounded retries, and keep an error log. Do not include the key in URL logs. Storing the input list and results separately helps identify which accounts have already been processed.

Expected result

The output is a JSON file containing a processing result for each submitted username, a timestamp, available attributes, and the saved response. Before passing the list to a campaign, you can filter matching usernames, private profiles, and technical cases for manual review. The team sets the criteria for the next step.

The endpoint and parameters are described in the IG API documentation; product information is available on the IG Scraper API page. Start with a small sample, check the actual response format, and configure the report rules for your workflow.

People

No people listed for this article yet.

Keep readingTurn IG Profiles into a Daily Change Log
Read the next article

Turn what you read into a working integration

Explore jsonscraper's social-data APIs, test requests and build your next workflow.

Explore APIs