st1vms/unofficial-claude-api

brotli.error and 403

HokkaidoInu opened this issue · 16 comments

I was using the API a couple of days ago and it was working fine.

Errors:

When using create_chat() I got Message limit hit, cannot create chat... (which I know is incorrect because I have messages left) so I changed the code and printed the response.status_code and got 403

When using send_message() I get brotli.error: BrotliDecompress failed

When using get_all_chat_ids() I get an empty array (which I know is incorrect because I have conversations) so I changed the code and printed the response.status_code and got 403

What I have tried:

Changing the __BASE_URL from "https://claude.ai" to "https://api.claude.ai" Host in headers from "claude.ai" to "api.claude.ai".
Using a US VPN connection.

Ok so I got it working now the non selenium way for get_all_chat_ids() and create_chat().

And the send_message() works for sending the message but still getting the brotli.error for the returned content.
So I'll try to see what's causing that and then see about why the selenium way isn't working.

The error is caused by this line:

return br_decompress(buffer)

Apparently the br encoding header is hit, and the brotli decompression fails probably because of unexpected data.

Without knowing the content of the response at the time of decompression, it is hard to know the reason why it fails. Also because it happens before a SendMessageResponse is constructed.

@HokkaidoInu Could you please install this library from source using pip install -e ./repo_dir ?
You should then be able to inspect the response by doing a print(response.content) inside send_message at line 617:

...and also inspect the encoding header received with a print(enc) in the same line.

Thanks for your feedback!

@HokkaidoInu Alternatively you could try switching to the new branch decoding_errors, it wraps the decoding exception and it returns the raw response already.

Ok so I got it working now the non selenium way for get_all_chat_ids() and create_chat().

And the send_message() works for sending the message but still getting the brotli.error for the returned content. So I'll try to see what's causing that and then see about why the selenium way isn't working.

So you say crafting the SessionData yourself worked instead of using get_session_data()? Did you call get_session_data with no parameters? Or did you give it a path? Maybe you inserted the wrong Firefox profile path, or the login expired.

The error is caused by this line:

return br_decompress(buffer)

I figured out the reason is because even though it says that the content-encoding is br, when I printed out the response.content it returned a byte response like this b'[{"geonameId:"703448"}..........'. mentioned in this stack overflow question and so because in here

def __parse_send_message_response(self, data_bytes: bytes) -> str | None:

is run data_bytes.decode
so this
return br_decompress(buffer)

just needs to be changed from br_decompress(buffer) to buffer

So you say crafting the SessionData yourself worked instead of using get_session_data()? Did you call get_session_data with no parameters? Or did you give it a path? Maybe you inserted the wrong Firefox profile path, or the login expired.

As for this I was using it with no parameters, but I just tried with profile="~/.mozilla/firefox/xxt7bfge.default-release" and got "No such file or directory"

The error is caused by this line:

return br_decompress(buffer)

I figured out the reason is because even though it says that the content-encoding is br, when I printed out the response.content it returned a byte response like this b'[{"geonameId:"703448"}..........'. mentioned in this stack overflow question and so because in here

def __parse_send_message_response(self, data_bytes: bytes) -> str | None:

is run data_bytes.decode
so this

return br_decompress(buffer)

just needs to be changed from br_decompress(buffer) to buffer

Since I already received complaints about this error, I decided to drop the Brotli decoding.
Changes are already live on the new branch, but I don't know if I'll merge into main any time soon without some feedback...

So you say crafting the SessionData yourself worked instead of using get_session_data()? Did you call get_session_data with no parameters? Or did you give it a path? Maybe you inserted the wrong Firefox profile path, or the login expired.

As for this I was using it with no parameters, but I just tried with profile="~/.mozilla/firefox/xxt7bfge.default-release" and got "No such file or directory"

This is because It doesn't support path expansion, you need to provide the absolute path to the profile.

This is because It doesn't support path expansion, you need to provide the absolute path to the profile.

Unfortunately it still shows Message limit hit, cannot create chat... with the profile. I am able to print the session and that looks good, so it is connecting I guess.

This is because It doesn't support path expansion, you need to provide the absolute path to the profile.

Unfortunately it still shows Message limit hit, cannot create chat... with the profile. I am able to print the session and that looks good, so it is connecting I guess.

Since I can't reproduce the error...can you inspect the response.content in create_chat too?

if response and response.status_code == 201:

Since I can't reproduce the error...can you inspect the response.content in create_chat too?

I get b'{"type":"error","error":{"type":"permission_error","message":"Invalid authorization for organization"}}'

I found out the reason behind get_session_data() not working for me.
It's because at https://claude.ai/api/organizations I get 2 objects in the array and the data is different in each as you can see here (changed json to markdown because idk how to pretty print json here):

uuid name settings.claude_console_privacy settings.allowed_invite_domains capabilities.0 rate_limit_tier billing_type free_credits_status data_retention api_disabled_reason api_disabled_until billable_usage_paused_until raven_type created_at updated_at active_flags
7685jh8-4nbvb7-b46nb-34nb6-hbhb63-notMyActualId NaN default_private api auto_api_evaluation default out_of_credits 2024-06-28T17:07:50.208422Z 2024-06-28T17:07:50.208422Z
43vy74yv-v3hj5-4366h-4b6-nb46b636-notMyActualId example@gmail.com's Organization default_private chat default_claude_ai default 2024-06-28T21:37:11.003687Z 2024-06-28T21:37:11.003687Z

So I had to change the 0 in this line to a 1

org_id = j[0]["uuid"]

I found out the reason behind get_session_data() not working for me. It's because at https://claude.ai/api/organizations I get 2 objects in the array and the data is different in each as you can see here (changed json to markdown because idk how to pretty print json here):
uuid name settings.claude_console_privacy settings.allowed_invite_domains capabilities.0 rate_limit_tier billing_type free_credits_status data_retention api_disabled_reason api_disabled_until billable_usage_paused_until raven_type created_at updated_at active_flags
7685jh8-4nbvb7-b46nb-34nb6-hbhb63-notMyActualId NaN default_private api auto_api_evaluation default out_of_credits 2024-06-28T17:07:50.208422Z 2024-06-28T17:07:50.208422Z
43vy74yv-v3hj5-4366h-4b6-nb46b636-notMyActualId example@gmail.com's Organization default_private chat default_claude_ai default 2024-06-28T21:37:11.003687Z 2024-06-28T21:37:11.003687Z

So I had to change the 0 in this line to a 1

org_id = j[0]["uuid"]

It means your account has multiple organizations...

At this point what I can do is to retrieve by default the last element in this array by indexing with -1 since the latest organization will always be the last. And also leave an integer parameter in get_session_data called organization_index to override it.

I've also made a section in the README, all changes are already in the attached branch of this issue, they will be merged after feedback.

@HokkaidoInu Waiting for feedback before merging the new branch into main, I'll have to create a new release so I'd like to know if everything works now.

@HokkaidoInu Waiting for feedback before merging the new branch into main, I'll have to create a new release so I'd like to know if everything works now.

All works fine for me on the new branch. Thank you 🎉

Nice!

Auto closing this issue once the new branch is published.