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
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)