Skip to content

Instantly share code, notes, and snippets.

@2shrestha22
Last active July 25, 2025 03:52
Show Gist options
  • Select an option

  • Save 2shrestha22/3b0f76c37c1775f7b9ec693461b7aa82 to your computer and use it in GitHub Desktop.

Select an option

Save 2shrestha22/3b0f76c37c1775f7b9ec693461b7aa82 to your computer and use it in GitHub Desktop.
Request bootloader unlock for Xiaomi devices
import subprocess
import sys
import os
# Configuration
FEED_TIME_SHIFT = 1400 # Time shift in milliseconds - adjust this value as needed
# Server lists
ntp_servers = [
"ntp0.ntp-servers.net", "ntp1.ntp-servers.net", "ntp2.ntp-servers.net",
"ntp3.ntp-servers.net", "ntp4.ntp-servers.net", "ntp5.ntp-servers.net",
"ntp6.ntp-servers.net"
]
MI_SERVERS = ['161.117.96.161', '20.157.18.26']
# Installation of dependencies
def install_package(package):
subprocess.check_call([sys.executable, "-m", "pip", "install", package])
required_packages = ["requests", "ntplib", "pytz", "urllib3", "linecache"]
for package in required_packages:
try:
__import__(package)
except ImportError:
print(f"Installing package {package}...")
install_package(package)
os.system('cls' if os.name == 'nt' else 'clear')
import hashlib
import random
import time
from datetime import datetime, timezone, timedelta
import ntplib
import pytz
import urllib3
import json
# Version
os.system('cls' if os.name == 'nt' else 'clear')
scriptversion = "ARU_FHL_v070425"
# Global variables
print(f"{scriptversion}")
print(f"\nChecking account status")
token = open("token.txt").read().strip().split()[0]
cookie_value = token
feed_time_shift = FEED_TIME_SHIFT
feed_time_shift_1 = feed_time_shift / 1000
# Generates a unique device identifier
def generate_device_id():
random_data = f"{random.random()}-{time.time()}"
device_id = hashlib.sha1(random_data.encode('utf-8')).hexdigest().upper()
return device_id
# Get the current Beijing time from NTP
def get_initial_beijing_time():
client = ntplib.NTPClient()
beijing_tz = pytz.timezone("Asia/Shanghai")
for server in ntp_servers:
try:
print(f"\nGetting current Beijing time")
response = client.request(server, version=3)
ntp_time = datetime.fromtimestamp(response.tx_time, timezone.utc)
beijing_time = ntp_time.astimezone(beijing_tz)
print(f"[Beijing time]: {beijing_time.strftime('%Y-%m-%d %H:%M:%S.%f')}")
return beijing_time
except Exception as e:
print(f"Error connecting to {server}: {e}")
print(f"Could not connect to any NTP server.")
return None
# Synchronize Beijing time
def get_synchronized_beijing_time(start_beijing_time, start_timestamp):
elapsed = time.time() - start_timestamp
current_time = start_beijing_time + timedelta(seconds=elapsed)
return current_time
# Wait until the target time taking into account the ping
def wait_until_target_time(start_beijing_time, start_timestamp):
next_day = start_beijing_time + timedelta(days=1)
print(f"\nBootloader unlock request")
print(f"[Set offset]: {feed_time_shift:.2f} ms.")
target_time = next_day.replace(hour=0, minute=0, second=0, microsecond=0) - timedelta(seconds=feed_time_shift_1)
print(f"[Waiting until]: {target_time.strftime('%Y-%m-%d %H:%M:%S.%f')}")
print(f"\nDo not close this window...")
while True:
current_time = get_synchronized_beijing_time(start_beijing_time, start_timestamp)
time_diff = target_time - current_time
if time_diff.total_seconds() > 1:
time.sleep(min(1.0, time_diff.total_seconds() - 1))
elif current_time >= target_time:
print(f"Target time reached: {current_time.strftime('%Y-%m-%d %H:%M:%S.%f')}. Starting to send requests...")
break
else:
time.sleep(0.0001)
# Check if account unlocking is possible via API
def check_unlock_status(session, cookie_value, device_id):
try:
url = "https://sgp-api.buy.mi.com/bbs/api/global/user/bl-switch/state"
headers = {
"Cookie": f"new_bbs_serviceToken={cookie_value};versionCode=500411;versionName=5.4.11;deviceId={device_id};"
}
response = session.make_request('GET', url, headers=headers)
if response is None:
print(f"[Error] Could not get unlock status.")
return False
response_data = json.loads(response.data.decode('utf-8'))
response.release_conn()
if response_data.get("code") == 100004:
print(f"[Error] Cookie has expired, needs to be updated.")
input(f"Press Enter to close...")
exit()
data = response_data.get("data", {})
is_pass = data.get("is_pass")
button_state = data.get("button_state")
deadline_format = data.get("deadline_format", "")
if is_pass == 4:
if button_state == 1:
print(f"[Account status]: request can be sent.")
return True
elif button_state == 2:
print(f"[Account status]: request block until {deadline_format} (Month/Day).")
status_2 = (input(f"Continue (Yes/No)?: ") )
if (status_2 == 'y' or status_2 == 'Y' or status_2 == 'yes' or status_2 == 'Yes' or status_2 == 'YES'):
return True
else:
input(f"Press Enter to close...")
exit()
elif button_state == 3:
print(f"[Account status]: account was created less than 30 days ago.")
status_3 = (input(f"Continue (Yes/No)?: ") )
if (status_3 == 'y' or status_3 == 'Y' or status_3 == 'yes' or status_3 == 'Yes' or status_3 == 'YES'):
return True
else:
input(f"Press Enter to close...")
exit()
elif is_pass == 1:
print(f"[Account status]: request was approved, unlock is possible until {deadline_format}.")
input(f"Press Enter to close...")
exit()
else:
print(f"[Account status]: unknown status.")
input(f"Press Enter to close...")
exit()
except Exception as e:
print(f"[Status check error] {e}")
return False
# Container for working with HTTP requests
class HTTP11Session:
def __init__(self):
self.http = urllib3.PoolManager(
maxsize=10,
retries=True,
timeout=urllib3.Timeout(connect=2.0, read=15.0),
headers={}
)
def make_request(self, method, url, headers=None, body=None):
try:
request_headers = {}
if headers:
request_headers.update(headers)
request_headers['Content-Type'] = 'application/json; charset=utf-8'
if method == 'POST':
if body is None:
body = '{"is_retry":true}'.encode('utf-8')
request_headers['Content-Length'] = str(len(body))
request_headers['Accept-Encoding'] = 'gzip, deflate, br'
request_headers['User-Agent'] = 'okhttp/4.12.0'
request_headers['Connection'] = 'keep-alive'
response = self.http.request(
method,
url,
headers=request_headers,
body=body,
preload_content=False
)
return response
except Exception as e:
print(f"[Network error] {e}")
return None
def main():
device_id = generate_device_id()
session = HTTP11Session()
if check_unlock_status(session, cookie_value, device_id):
start_beijing_time = get_initial_beijing_time()
if start_beijing_time is None:
print(f"Could not establish initial time. Press Enter to close...")
input()
exit()
start_timestamp = time.time()
wait_until_target_time(start_beijing_time, start_timestamp)
url = "https://sgp-api.buy.mi.com/bbs/api/global/apply/bl-auth"
headers = {
"Cookie": f"new_bbs_serviceToken={cookie_value};versionCode=500411;versionName=5.4.11;deviceId={device_id};"
}
try:
while True:
request_time = get_synchronized_beijing_time(start_beijing_time, start_timestamp)
print(f"[Request]: Sending request at {request_time.strftime('%Y-%m-%d %H:%M:%S.%f')} (UTC+8)")
response = session.make_request('POST', url, headers=headers)
if response is None:
continue
response_time = get_synchronized_beijing_time(start_beijing_time, start_timestamp)
print(f"[Response]: Response received at {response_time.strftime('%Y-%m-%d %H:%M:%S.%f')} (UTC+8)")
try:
response_data = response.data
response.release_conn()
json_response = json.loads(response_data.decode('utf-8'))
code = json_response.get("code")
data = json_response.get("data", {})
if code == 0:
apply_result = data.get("apply_result")
if apply_result == 1:
print(f"[Status]: Request was approved, checking status...")
check_unlock_status(session, cookie_value, device_id)
elif apply_result == 3:
deadline_format = data.get("deadline_format", "Not specified")
print(f"[Status]: Request was not sent, limit reached. Try again on {deadline_format} (Month/Day).")
input(f"Press Enter to close...")
exit()
elif apply_result == 4:
deadline_format = data.get("deadline_format", "Not specified")
print(f"[Status]: Request was not sent, block imposed until {deadline_format} (Month/Day).")
input(f"Press Enter to close...")
exit()
elif code == 100001:
print(f"[Status]: Request was rejected, error in the request.")
print(f"[FULL RESPONSE]: {json_response}")
elif code == 100003:
print(f"[Status]: Request may have been approved, checking status...")
print(f"[Full response]: {json_response}")
check_unlock_status(session, cookie_value, device_id)
elif code is not None:
print(f"[Status]: Unknown request status: {code}")
print(f"[Full response]: {json_response}")
else:
print(f"[Error]: Response does not contain required code.")
print(f"[Full response]: {json_response}")
except json.JSONDecodeError:
print(f"[Error]: Could not decode JSON response.")
print(f"[Server response]: {response_data}")
except Exception as e:
print(f"[Response processing error]: {e}")
continue
except Exception as e:
print(f"[Request error]: {e}")
input(f"Press Enter to close...")
exit()
if __name__ == "__main__":
main()
replace_this_with_new_bbs_serviceToken_value
@2shrestha22
Copy link
Author

2shrestha22 commented Jul 18, 2025

This script will help you to automate sending bootloader unlock request instead of using Xiaomi Community app which always gives quota limit reached error. Bootloader unlock is only allowed in Global ROMs

  • download this gist as a zip
  • install Cookie Editor extension of Firefox (other browser may not work)
  • login with your MI account on https://c.mi.com/global
  • grab new_bbs_serviceToken from cookies using Cookie Editor
  • update token.txt to write down new_bbs_serviceToken
  • run above python script, python3 bootloader-unlock-req.py
  • wait for China time, 24:00 to send unlock request automatically
  • no matter what the result says, you should try adding account in Developer Options

Credit: https://xdaforums.com/t/how-to-unlock-bootloader-on-xiaomi-hyperos-all-devices-except-cn.4654009/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment