Holehe Instagram Email Checking Logic: How It Simulates Sign-Up Flow

Holehe verifies whether an email is registered on Instagram by simulating the platform's sign-up flow, extracting CSRF tokens from the public signup page, submitting fake registration payloads to an internal AJAX endpoint, and parsing JSON error responses for specific patterns like "email_is_taken" or "email_sharing_limit".

The open-source OSINT tool Holehe checks email registration status across hundreds of services by exploiting public account creation endpoints. In the megadose/holehe repository, the Instagram module implements a sophisticated email existence verification that mimics legitimate user registration attempts without creating actual accounts. This approach leverages Instagram's own validation infrastructure to leak account existence information through error messages.

Overview of the Instagram Email Verification Flow

The Instagram email checking logic operates by exploiting Instagram's web-based account creation API. Rather than using public profile lookup endpoints—which often require authentication—the module submits incomplete registration attempts to trigger validation errors that expose whether an email is already in use.

This method avoids authentication barriers while providing reliable boolean results for email existence, rate-limit detection, and error handling through a standardized output schema.

Step-by-Step Implementation in holehe/modules/social_media/instagram.py

The core logic resides in holehe/modules/social_media/instagram.py, where the primary function orchestrates a four-phase verification process using asynchronous HTTP requests.

Fetching the CSRF Token

First, Holehe establishes a session and extracts the required anti-forgery token. The module sends a GET request to /accounts/emailsignup/ and parses the HTML response to retrieve the hidden CSRF token embedded in the page's form fields.

This token extraction occurs at lines 21-23 of instagram.py. The code isolates the csrf_token value necessary for subsequent POST requests, storing it for the validation phase.

Constructing the Registration Payload

Next, the module prepares a payload designed to trigger email validation without completing registration. The code generates a random username and sets an empty first name while inserting the target email verbatim into the POST body.

As implemented at lines 31-37, this payload includes:

  • email: The target address being checked
  • username: A randomly generated string to avoid conflicts
  • first_name: An empty string
  • opt_into_one_tap: Set to false

Submitting to the Internal AJAX Endpoint

With the CSRF token and payload ready, Holehe submits the request to Instagram's internal validation endpoint. The POST request targets /api/v1/web/accounts/web_create_ajax/attempt/ with the CSRF token included in the x-csrftoken header.

Lines 38-42 handle this submission, using the asynchronous HTTP client from holehe/core.py to send the request with appropriate headers and cookie contexts established during the initial token fetch.

Parsing the JSON Response

The response interpretation logic determines whether the email exists based on specific error patterns. If the response status is not "fail", the code inspects check["errors"]["email"] for two specific indicators:

  • "email_is_taken": The error code confirming the email is already registered
  • "email_sharing_limit": A secondary string pattern indicating the email has reached usage limits

Lines 44-58 implement this check, returning exists = True when either pattern appears. If these error patterns are absent, lines 60-66 set exists = False, indicating the email is available for registration.

Handling Rate Limits and Edge Cases

When Instagram returns a response with status "fail", the module assumes rate-limiting has been applied. Lines 67-73 catch this condition, setting rateLimit = True and exists = None to indicate the check could not complete due to throttling.

All results append to the shared out list as structured dictionaries containing:

  • name: "instagram"
  • domain: "instagram.com"
  • method: "register"
  • exists: Boolean or None
  • rateLimit: Boolean indicating throttling status
  • frequent_rate_limit: Predefined service-specific flag
  • emailrecovery, phoneNumber, others: Additional metadata fields (typically None for this module)

Practical Implementation Example

To check an email programmatically using Holehe's Instagram module:

import asyncio
from holehe import core
from holehe.modules.social_media import instagram

async def check_instagram(email):
    async with core.Client() as client:
        out = []
        await instagram.instagram(email, client, out)
        return out[0]

result = asyncio.run(check_instagram("test@example.com"))
print(result)

This returns a standardized dictionary detailing the verification outcome, including existence status and rate-limit detection.

Summary

  • Holehe's Instagram module exploits the /api/v1/web/accounts/web_create_ajax/attempt/ endpoint to verify email registration status without completing account creation.
  • The implementation requires CSRF token extraction from /accounts/emailsignup/ before submitting fake registration payloads with randomized usernames.
  • Email existence is determined by parsing error codes "email_is_taken" or strings containing "email_sharing_limit" in the JSON response at lines 44-58.
  • Rate limiting detection occurs when the response status equals "fail", triggering the rateLimit = True flag at lines 67-73.
  • All results follow the standardized schema defined in holehe/modules/social_media/instagram.py, enabling consistent integration with Holehe's broader OSINT framework.

Frequently Asked Questions

What specific error codes indicate an email is already registered on Instagram?

Instagram's API returns "email_is_taken" in the error object when an email is already associated with an existing account. Additionally, Holehe checks for the substring "email_sharing_limit", which appears when an email has reached the maximum number of allowed registrations. Both patterns trigger the exists = True result in the output dictionary.

How does Holehe avoid detection when checking multiple emails?

The module randomizes usernames for each request and relies on the core.Client class from holehe/core.py, which manages sessions and retries. However, aggressive usage still triggers Instagram's rate-limiting protections, which the module detects via the "fail" status code and reports through the rateLimit field.

Can this method detect if an email has account recovery options enabled?

No. The current implementation in holehe/modules/social_media/instagram.py focuses exclusively on existence detection via the registration endpoint. While the output schema reserves fields for emailrecovery and phoneNumber, the Instagram module populates these with None as the AJAX endpoint used does not return account recovery metadata.

What happens when Instagram returns an unexpected response format?

If the JSON response lacks the expected error structure or contains a "fail" status unrelated to rate-limiting, the module conservatively sets exists = False while allowing the exception to propagate. The error handling at lines 60-73 ensures the tool continues functioning even when Instagram modifies their API responses, preventing false positives.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →