Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ jobs:
tests/regression/test_comments.py::CommentRepliesRegressionTestCase \
tests/regression/test_current_app_profile.py::CurrentAppProfileRegressionTestCase \
tests/regression/test_auth_story.py::AuthAndStoryRegressionTestCase \
tests/regression/test_attestation.py::CaaLoginRegressionTestCase \
tests/regression/test_download.py::DownloadRegressionTestCase \
tests/regression/test_notes.py::NoteMixinRegressionTestCase \
tests/regression/test_location.py::LocationMixinRegressionTestCase \
Expand Down
2 changes: 1 addition & 1 deletion docs/usage-guide/totp.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ cl.bloks_two_step_verification_enter_backup_code(context)
result = cl.bloks_two_step_verification_verify_code(context, "12345678", challenge="backup_codes")
```

`bloks_caa_login(...)` runs the complete current CAA sequence. For low-level inspection, call `bloks_caa_login_prepare(...)` before `bloks_caa_login_send_request(...)`; the send helper requires the account access context returned by Instagram during that preflight. `bloks_extract_two_step_verification_context(...)` extracts a legacy Bloks two-factor context when the login response exposes one.
`bloks_caa_login(...)` runs the complete current CAA sequence. For low-level inspection, `bloks_caa_login_send_request(...)` now runs `bloks_caa_login_prepare(...)` automatically when the client has no server-issued account access context; existing prepared context is reused on later calls. Its domain, waterfall ID, offline experiment group, and Bloks versioning ID overrides are forwarded to that automatic preflight. Pass `auto_prepare=False` to require pre-existing state, or call the preparation helper explicitly when you need to inspect or control the preflight separately. `bloks_extract_two_step_verification_context(...)` extracts a legacy Bloks two-factor context when the login response exposes one.

`bloks_extract_login_response(...)` returns decoded `login_response`, response `headers`, cookie values, raw cookie header text, and the raw embedded object when Instagram returns a successful Bloks login payload. It returns `{}` when the response is an intermediate UI state or an error. `bloks_apply_login_response(...)` can then copy the returned authorization data and cookies into the current client session.

Expand Down
67 changes: 57 additions & 10 deletions instagrapi/mixins/bloks.py
Original file line number Diff line number Diff line change
Expand Up @@ -604,16 +604,34 @@ def bloks_caa_login_oauth_token_fetch(
login=True,
)

def bloks_caa_login_prepare(self, username: str = "", domain: Optional[str] = None) -> bool:
def bloks_caa_login_prepare(
self,
username: str = "",
domain: Optional[str] = None,
waterfall_id: str = "",
offline_experiment_group: str = "caa_iteration_v3_perf_ig_4",
bloks_versioning_id: str = "",
) -> bool:
"""Run the ordered device and CAA preflight needed before login."""
if not self.usdid_registered and not self.usdid_register():
return False
self.bloks_caa_login_process_client_data(domain=domain)
self.bloks_caa_login_process_client_data(
waterfall_id=waterfall_id,
offline_experiment_group=offline_experiment_group,
bloks_versioning_id=bloks_versioning_id,
domain=domain,
)
self.attestation_challenge_nonce = ""
self.attestation_key_nonce = ""
self.attestation_create_android_keystore(domain=domain)
if self.caa_aac:
self.bloks_caa_login_oauth_token_fetch(username=username, domain=domain)
self.bloks_caa_login_oauth_token_fetch(
username=username,
waterfall_id=waterfall_id,
offline_experiment_group=offline_experiment_group,
bloks_versioning_id=bloks_versioning_id,
domain=domain,
)
return bool(self.caa_aac and self.attestation_challenge_nonce)

def bloks_caa_login_send_request(
Expand All @@ -626,27 +644,51 @@ def bloks_caa_login_send_request(
offline_experiment_group: str = "caa_iteration_v3_perf_ig_4",
bloks_versioning_id: str = "",
domain: Optional[str] = None,
auto_prepare: bool = True,
) -> Dict:
"""
Send the current CAA/Bloks login request used before Bloks 2FA.

This low-level helper requires the server-issued account access context
and uses the attestation state populated by
:meth:`bloks_caa_login_prepare`.
When needed, this low-level helper obtains the server-issued account
access context through :meth:`bloks_caa_login_prepare` before encrypting
the password. Set ``auto_prepare=False`` to require pre-existing state.

Returns
-------
Dict
Raw Instagram response.
"""
contact_point = username or self.username
encrypted_password = password if password.startswith("#PWD_") else self.password_encrypt(password)
flow_id = waterfall_id or self.caa_waterfall_id or str(uuid4())
self.caa_waterfall_id = flow_id
if auto_prepare and not self.caa_aac:
preflight_state = (
self.caa_aac,
self.caa_waterfall_id,
self.attestation_challenge_nonce,
self.attestation_key_nonce,
)
try:
self.bloks_caa_login_prepare(
username=contact_point,
domain=domain,
waterfall_id=waterfall_id,
offline_experiment_group=offline_experiment_group,
bloks_versioning_id=bloks_versioning_id,
)
except Exception:
(
self.caa_aac,
self.caa_waterfall_id,
self.attestation_challenge_nonce,
self.attestation_key_nonce,
) = preflight_state
raise
if not self.caa_aac:
raise ClientError(
"CAA login requires a server-issued aac; call bloks_caa_login_prepare() before send_login_request"
)
encrypted_password = password if password.startswith("#PWD_") else self.password_encrypt(password)
flow_id = waterfall_id or self.caa_waterfall_id or str(uuid4())
self.caa_waterfall_id = flow_id
# Recent CAA login screens emit short base36-like input ids. Hex-only
# UUID prefixes are accepted by the VM but can return a null-payload 404.
text_input_id = f"{uuid4().hex[:4]}ig"
Expand Down Expand Up @@ -762,7 +804,12 @@ def bloks_caa_login(
"two_step": {},
"reason": "CAA preflight did not return account access and attestation data",
}
result = self.bloks_caa_login_send_request(password, username=username, domain=domain)
result = self.bloks_caa_login_send_request(
password,
username=username,
domain=domain,
auto_prepare=prepare,
)
logged_in = self.bloks_apply_login_response(result)
two_step = {}
if not logged_in and self.bloks_caa_login_needs_two_step(result):
Expand Down
Loading