Reverse Engineering the Instagram Login Process

刘胖孩
刘胖孩
我们可以看到这是一个没有缓存能力的管道,然后往里面写666,然后就去管道里面读。这样肯定会出现问题啊!一个无缓存能力的管道,没有人读,你也写不了,没有人写,你也读不了,这正是一种死锁! 解决办法很简单,开辟两条协程,一条协程写,一条协程读。

Want to automate Instagram logins? You’ll quickly find that a simple POST request will only result in a harsh 403 rejection. After some research, we discovered two major "firewalls" in the login process: the CSRF token and frontend password encryption.
Our analysis shows that the password is encrypted, and the request headers must include the x-csrftoken when sending the POST request; otherwise, a 403 error is returned. The x-csrftoken is set during the first visit to the homepage. By mimicking the behavior of a real user—first accessing Instagram’s homepage—the server passes this "verification token" to the client via cookies. This is the first key to breaking through the login barrier.
As for password handling: if the plaintext password is "111111", it is transformed into an encrypted string prefixed with #PWD_INSTAGRAM_BROWSER before being sent. We need to dive deep into the logic behind the code and crack it step by step.
First, you can locate where the login request is generated by examining the "request stack." Alternatively, you can perform a global search for enc_password to find its generation point. The core logic lies in i(d[1]).encrypt(t, c, u, f), which can be executed in a Node environment.
Next, set breakpoints for debugging. Observe the input of critical parameters such as the plaintext password, timestamp, and public key at the entry point of the encryption function. Then, track the generation of the final encrypted result at the exit point to fully reconstruct the entire process: "plaintext password + auxiliary parameters → processed by the core function i(d[1]).encrypt(...) → generates the encrypted string."
Finally, should we recreate this complex encryption logic from scratch in Python, or directly reuse the original JavaScript encryption code? We opted for the more efficient latter approach: encapsulating this core JS encryption logic into a local Node.js service. This way, the main Python program only needs to pass the plaintext password to this Node.js service as if calling a regular API, and it quickly receives the encrypted password that meets the requirements.
Code example: (Python)

Python Copy
import requests
import json
INSTAGRAM_USERNAME = "15566678899"
INSTAGRAM_PASSWORD = "1111111111111111111111"

PROXY_IP = "your_proxy_ip:port" # <--- Enter your proxy IP and port here.
ENCRYPTION_SERVICE_URL = "http://localhost:23346/instagram"

def get_proxy(ip_string):
    if not ip_string:
        return None # If no IP is provided, do not use a proxy.
    return {
        "http": f"http://{ip_string}",
        "https": f"https://{ip_string}",
    }

def get_encrypted_password(password, service_url):
    try:
        print("Calling the local encryption service....")
        response = requests.get(service_url, params={"password": password}, timeout=5) #Add a 5-second timeout
        response.raise_for_status()  
        encrypted_password = response.text
        if not encrypted_password.startswith("#PWD_INSTAGRAM_BROWSER"):
            raise ValueError("The format returned by the encryption service is incorrect.")
        print("✅ Encryption password obtained successfully!")
        return encrypted_password
    except requests.exceptions.RequestException as e:
        print(f"❌ Failed to call the encryption service: {e}")
        return None
    except ValueError as e:
        print(f"❌ The encryption service returned a data error.: {e}")
        return None

def login_to_instagram(username, password):
    session = requests.Session()
    proxies = get_proxy(PROXY_IP)

    session.headers.update({
        'authority': 'www.instagram.com',
        'origin': 'https://www.instagram.com',
        'referer': 'https://www.instagram.com/',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36', # Update to a more modern UA
    })

    try:
        print("Accessing the Instagram homepage forcsrftoken...")
        response_initial = session.get('https://www.instagram.com/', proxies=proxies, timeout=15)
        response_initial.raise_for_status()
        
        csrf_token = session.cookies.get('csrftoken')
        if not csrf_token:
            raise ValueError("Unable to retrieve from the homepage response.csrftoken。")
        
        print(f"✅ csrftokenSuccessfully obtained: {csrf_token[:10]}...")
        
        session.headers.update({'x-csrftoken': csrf_token})

        enc_password = get_encrypted_password(password, ENCRYPTION_SERVICE_URL)
        if not enc_password:
            return # If encryption fails, terminate login.

        login_data = {
            'enc_password': enc_password,
            'username': username,
            'queryParams': '{}',
            'optIntoOneTap': 'false',
            'stopDeletionNonce': '',
            'trustedDeviceRecords': '{}'
        }
        
        print(f"Trying to log in as user '{username}'...")
        response_login = session.post(
            'https://www.instagram.com/accounts/login/ajax/',
            data=login_data,
            proxies=proxies,
            timeout=15
        )
        response_login.raise_for_status()

        print(f"Response status code: {response_login.status_code}")
        login_result = response_login.json()
        print("Response content:")
        print(json.dumps(login_result, indent=2, ensure_ascii=False))
        if login_result.get("authenticated"):
            print("\n? Login successful!")
        else:
            print(f"\n❌ Login failed: {login_result.get('message', 'Unknown error')}")

    except requests.exceptions.RequestException as e:
        print(f"❌ An error occurred during the network request.: {e}")
    except ValueError as e:
        print(f"❌An error occurred during data processing.: {e}")
    except Exception as e:
        print(f"❌ An unknown error occurred.: {e}")

if __name__ == "__main__":
    login_to_instagram(INSTAGRAM_USERNAME, INSTAGRAM_PASSWORD)
Update Time:Feb 03, 2026

Comments

Tips: Support some markdown syntax: **bold**, [bold](xxxxxxxxx), `code`, - list, > reference