curl_cffi ErrCode: 35
merlinarer opened this issue · 5 comments
Traceback (most recent call last):
File "D:\proj\test.py", line 111, in <module>
claude_api = Client(cookie)
^^^^^^^^^^^^^^
File "D:\app\miniconda3\Lib\site-packages\claude_api.py", line 12, in __init__
self.organization_id = self.get_organization_id()
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\app\miniconda3\Lib\site-packages\claude_api.py", line 30, in get_organization_id
response = requests.get(url, headers=headers,impersonate="chrome110")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\app\miniconda3\Lib\site-packages\curl_cffi\requests\__init__.py", line 46, in request
return s.request(
^^^^^^^^^^
File "D:\app\miniconda3\Lib\site-packages\curl_cffi\requests\session.py", line 438, in request
raise RequestsError(e)
curl_cffi.requests.errors.RequestsError: Failed to perform, ErrCode: 35, Reason: 'BoringSSL SSL_connect: Connection was reset in connection to claude.ai:443 '
I met this problem using v1.0.15 with a VPN to access claude2, whlie early v1.0.14 works well. Does that curl_cffi have special configration with VPN ?
I have met same problem. The problem can be fixed by using urllib3==1.25.11 and add parameter of proxies to requests().
- Claude Servers Block Most Requests from the VPN, Use Proxies instead!
I have met same problem. The problem can be fixed by using urllib3==1.25.11 and add parameter of proxies to requests().
hi, I have met same problem, could you please share the code or how to solve the problem ? thanks a lot!
I have met same problem. The problem can be fixed by using urllib3==1.25.11 and add parameter of proxies to requests().
hi, I have met same problem, could you please share the code or how to solve the problem ? thanks a lot!
This is the code I am currently using.
import json
import os
import uuid
from curl_cffi import requests
import re
class Client:
def __init__(self, cookie, proxies):
self.cookie = cookie
self.proxies = proxies
self.timeout = 600
self.organization_id = self.get_organization_id()
def get_organization_id(self):
url = "https://claude.ai/api/organizations"
headers = {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
'Accept-Language': 'en-US,en;q=0.5',
'Referer': 'https://claude.ai/chats',
'Content-Type': 'application/json',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'Connection': 'keep-alive',
'Cookie': f'{self.cookie}'
}
response = requests.get(url, headers=headers, impersonate="chrome110", proxies=self.proxies, timeout=self.timeout)
res = json.loads(response.text)
uuid = res[0]['uuid']
return uuid
def get_content_type(self, file_path):
# Function to determine content type based on file extension
extension = os.path.splitext(file_path)[-1].lower()
if extension == '.pdf':
return 'application/pdf'
elif extension == '.txt':
return 'text/plain'
elif extension == '.csv':
return 'text/csv'
# Add more content types as needed for other file types
else:
return 'application/octet-stream'
# Lists all the conversations you had with Claude
def list_all_conversations(self):
url = f"https://claude.ai/api/organizations/{self.organization_id}/chat_conversations"
headers = {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
'Accept-Language': 'en-US,en;q=0.5',
'Referer': 'https://claude.ai/chats',
'Content-Type': 'application/json',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'Connection': 'keep-alive',
'Cookie': f'{self.cookie}'
}
response = requests.get(url, headers=headers, impersonate="chrome110", proxies=self.proxies, timeout=self.timeout)
conversations = response.json()
# Returns all conversation information in a list
if response.status_code == 200:
return conversations
else:
print(f"Error: {response.status_code} - {response.text}")
# Send Message to Claude
def send_message(self, prompt, conversation_id, attachment=None):
url = "https://claude.ai/api/append_message"
# Upload attachment if provided
attachments = []
if attachment:
attachment_response = self.upload_attachment(attachment)
if attachment_response:
attachments = [attachment_response]
else:
return {"Error: Invalid file format. Please try again."}
# Ensure attachments is an empty list when no attachment is provided
if not attachment:
attachments = []
payload = json.dumps({
"completion": {
"prompt": f"{prompt}",
"timezone": "Asia/Kolkata",
"model": "claude-2"
},
"organization_uuid": f"{self.organization_id}",
"conversation_uuid": f"{conversation_id}",
"text": f"{prompt}",
"attachments": attachments
})
headers = {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
'Accept': 'text/event-stream, text/event-stream',
'Accept-Language': 'en-US,en;q=0.5',
'Referer': 'https://claude.ai/chats',
'Content-Type': 'application/json',
'Origin': 'https://claude.ai',
'DNT': '1',
'Connection': 'keep-alive',
'Cookie': f'{self.cookie}',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'TE': 'trailers'
}
response = requests.post(url, headers=headers, data=payload, impersonate="chrome110", proxies=self.proxies, timeout=self.timeout)
decoded_data = response.content.decode("utf-8")
decoded_data = re.sub('\n+', '\n', decoded_data).strip()
data_strings = decoded_data.split('\n')
completions = []
for data_string in data_strings:
json_str = data_string[6:].strip()
data = json.loads(json_str)
if 'completion' in data:
completions.append(data['completion'])
answer = ''.join(completions)
# Returns answer
return answer
# Deletes the conversation
def delete_conversation(self, conversation_id):
url = f"https://claude.ai/api/organizations/{self.organization_id}/chat_conversations/{conversation_id}"
payload = json.dumps(f"{conversation_id}")
headers = {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
'Accept-Language': 'en-US,en;q=0.5',
'Content-Type': 'application/json',
'Content-Length': '38',
'Referer': 'https://claude.ai/chats',
'Origin': 'https://claude.ai',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'Connection': 'keep-alive',
'Cookie': f'{self.cookie}',
'TE': 'trailers'
}
response = requests.delete(url, headers=headers, data=payload, impersonate="chrome110", proxies=self.proxies, timeout=self.timeout)
# Returns True if deleted or False if any error in deleting
if response.status_code == 204:
return True
else:
return False
# Returns all the messages in conversation
def chat_conversation_history(self, conversation_id):
url = f"https://claude.ai/api/organizations/{self.organization_id}/chat_conversations/{conversation_id}"
headers = {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
'Accept-Language': 'en-US,en;q=0.5',
'Referer': 'https://claude.ai/chats',
'Content-Type': 'application/json',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'Connection': 'keep-alive',
'Cookie': f'{self.cookie}'
}
response = requests.get(url, headers=headers, impersonate="chrome110", proxies=self.proxies, timeout=self.timeout)
# List all the conversations in JSON
return response.json()
def generate_uuid(self):
random_uuid = uuid.uuid4()
random_uuid_str = str(random_uuid)
formatted_uuid = f"{random_uuid_str[0:8]}-{random_uuid_str[9:13]}-{random_uuid_str[14:18]}-{random_uuid_str[19:23]}-{random_uuid_str[24:]}"
return formatted_uuid
def create_new_chat(self):
url = f"https://claude.ai/api/organizations/{self.organization_id}/chat_conversations"
uuid = self.generate_uuid()
payload = json.dumps({"uuid": uuid, "name": ""})
headers = {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
'Accept-Language': 'en-US,en;q=0.5',
'Referer': 'https://claude.ai/chats',
'Content-Type': 'application/json',
'Origin': 'https://claude.ai',
'DNT': '1',
'Connection': 'keep-alive',
'Cookie': self.cookie,
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'TE': 'trailers'
}
response = requests.post(url, headers=headers, data=payload, impersonate="chrome110", proxies=self.proxies, timeout=self.timeout)
# Returns JSON of the newly created conversation information
return response.json()
# Resets all the conversations
def reset_all(self):
conversations = self.list_all_conversations()
for conversation in conversations:
conversation_id = conversation['uuid']
delete_id = self.delete_conversation(conversation_id)
return True
def upload_attachment(self, file_path):
if file_path.endswith('.txt'):
file_name = os.path.basename(file_path)
file_size = os.path.getsize(file_path)
file_type = "text/plain"
with open(file_path, 'r', encoding='utf-8') as file:
file_content = file.read()
return {
"file_name": file_name,
"file_type": file_type,
"file_size": file_size,
"extracted_content": file_content
}
url = 'https://claude.ai/api/convert_document'
headers = {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
'Accept-Language': 'en-US,en;q=0.5',
'Referer': 'https://claude.ai/chats',
'Origin': 'https://claude.ai',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'Connection': 'keep-alive',
'Cookie': f'{self.cookie}',
'TE': 'trailers'
}
file_name = os.path.basename(file_path)
content_type = self.get_content_type(file_path)
files = {
'file': (file_name, open(file_path, 'rb'), content_type),
'orgUuid': (None, self.organization_id)
}
response = requests.post(url, headers=headers, files=files, impersonate="chrome110", proxies=self.proxies, timeout=self.timeout)
if response.status_code == 200:
return response.json()
else:
return False
# Renames the chat conversation title
def rename_chat(self, title, conversation_id):
url = "https://claude.ai/api/rename_chat"
payload = json.dumps({
"organization_uuid": f"{self.organization_id}",
"conversation_uuid": f"{conversation_id}",
"title": f"{title}"
})
headers = {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
'Accept-Language': 'en-US,en;q=0.5',
'Content-Type': 'application/json',
'Referer': 'https://claude.ai/chats',
'Origin': 'https://claude.ai',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'Connection': 'keep-alive',
'Cookie': f'{self.cookie}',
'TE': 'trailers'
}
response = requests.post(url, headers=headers, data=payload, impersonate="chrome110", proxies=self.proxies, timeout=self.timeout)
if response.status_code == 200:
return True
else:
return False
I have met same problem. The problem can be fixed by using urllib3==1.25.11 and add parameter of proxies to requests().
hi, I have met same problem, could you please share the code or how to solve the problem ? thanks a lot!
This is the code I am currently using.
import json import os import uuid from curl_cffi import requests import re class Client: def __init__(self, cookie, proxies): self.cookie = cookie self.proxies = proxies self.timeout = 600 self.organization_id = self.get_organization_id() def get_organization_id(self): url = "https://claude.ai/api/organizations" headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0', 'Accept-Language': 'en-US,en;q=0.5', 'Referer': 'https://claude.ai/chats', 'Content-Type': 'application/json', 'Sec-Fetch-Dest': 'empty', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'same-origin', 'Connection': 'keep-alive', 'Cookie': f'{self.cookie}' } response = requests.get(url, headers=headers, impersonate="chrome110", proxies=self.proxies, timeout=self.timeout) res = json.loads(response.text) uuid = res[0]['uuid'] return uuid def get_content_type(self, file_path): # Function to determine content type based on file extension extension = os.path.splitext(file_path)[-1].lower() if extension == '.pdf': return 'application/pdf' elif extension == '.txt': return 'text/plain' elif extension == '.csv': return 'text/csv' # Add more content types as needed for other file types else: return 'application/octet-stream' # Lists all the conversations you had with Claude def list_all_conversations(self): url = f"https://claude.ai/api/organizations/{self.organization_id}/chat_conversations" headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0', 'Accept-Language': 'en-US,en;q=0.5', 'Referer': 'https://claude.ai/chats', 'Content-Type': 'application/json', 'Sec-Fetch-Dest': 'empty', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'same-origin', 'Connection': 'keep-alive', 'Cookie': f'{self.cookie}' } response = requests.get(url, headers=headers, impersonate="chrome110", proxies=self.proxies, timeout=self.timeout) conversations = response.json() # Returns all conversation information in a list if response.status_code == 200: return conversations else: print(f"Error: {response.status_code} - {response.text}") # Send Message to Claude def send_message(self, prompt, conversation_id, attachment=None): url = "https://claude.ai/api/append_message" # Upload attachment if provided attachments = [] if attachment: attachment_response = self.upload_attachment(attachment) if attachment_response: attachments = [attachment_response] else: return {"Error: Invalid file format. Please try again."} # Ensure attachments is an empty list when no attachment is provided if not attachment: attachments = [] payload = json.dumps({ "completion": { "prompt": f"{prompt}", "timezone": "Asia/Kolkata", "model": "claude-2" }, "organization_uuid": f"{self.organization_id}", "conversation_uuid": f"{conversation_id}", "text": f"{prompt}", "attachments": attachments }) headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0', 'Accept': 'text/event-stream, text/event-stream', 'Accept-Language': 'en-US,en;q=0.5', 'Referer': 'https://claude.ai/chats', 'Content-Type': 'application/json', 'Origin': 'https://claude.ai', 'DNT': '1', 'Connection': 'keep-alive', 'Cookie': f'{self.cookie}', 'Sec-Fetch-Dest': 'empty', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'same-origin', 'TE': 'trailers' } response = requests.post(url, headers=headers, data=payload, impersonate="chrome110", proxies=self.proxies, timeout=self.timeout) decoded_data = response.content.decode("utf-8") decoded_data = re.sub('\n+', '\n', decoded_data).strip() data_strings = decoded_data.split('\n') completions = [] for data_string in data_strings: json_str = data_string[6:].strip() data = json.loads(json_str) if 'completion' in data: completions.append(data['completion']) answer = ''.join(completions) # Returns answer return answer # Deletes the conversation def delete_conversation(self, conversation_id): url = f"https://claude.ai/api/organizations/{self.organization_id}/chat_conversations/{conversation_id}" payload = json.dumps(f"{conversation_id}") headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0', 'Accept-Language': 'en-US,en;q=0.5', 'Content-Type': 'application/json', 'Content-Length': '38', 'Referer': 'https://claude.ai/chats', 'Origin': 'https://claude.ai', 'Sec-Fetch-Dest': 'empty', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'same-origin', 'Connection': 'keep-alive', 'Cookie': f'{self.cookie}', 'TE': 'trailers' } response = requests.delete(url, headers=headers, data=payload, impersonate="chrome110", proxies=self.proxies, timeout=self.timeout) # Returns True if deleted or False if any error in deleting if response.status_code == 204: return True else: return False # Returns all the messages in conversation def chat_conversation_history(self, conversation_id): url = f"https://claude.ai/api/organizations/{self.organization_id}/chat_conversations/{conversation_id}" headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0', 'Accept-Language': 'en-US,en;q=0.5', 'Referer': 'https://claude.ai/chats', 'Content-Type': 'application/json', 'Sec-Fetch-Dest': 'empty', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'same-origin', 'Connection': 'keep-alive', 'Cookie': f'{self.cookie}' } response = requests.get(url, headers=headers, impersonate="chrome110", proxies=self.proxies, timeout=self.timeout) # List all the conversations in JSON return response.json() def generate_uuid(self): random_uuid = uuid.uuid4() random_uuid_str = str(random_uuid) formatted_uuid = f"{random_uuid_str[0:8]}-{random_uuid_str[9:13]}-{random_uuid_str[14:18]}-{random_uuid_str[19:23]}-{random_uuid_str[24:]}" return formatted_uuid def create_new_chat(self): url = f"https://claude.ai/api/organizations/{self.organization_id}/chat_conversations" uuid = self.generate_uuid() payload = json.dumps({"uuid": uuid, "name": ""}) headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0', 'Accept-Language': 'en-US,en;q=0.5', 'Referer': 'https://claude.ai/chats', 'Content-Type': 'application/json', 'Origin': 'https://claude.ai', 'DNT': '1', 'Connection': 'keep-alive', 'Cookie': self.cookie, 'Sec-Fetch-Dest': 'empty', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'same-origin', 'TE': 'trailers' } response = requests.post(url, headers=headers, data=payload, impersonate="chrome110", proxies=self.proxies, timeout=self.timeout) # Returns JSON of the newly created conversation information return response.json() # Resets all the conversations def reset_all(self): conversations = self.list_all_conversations() for conversation in conversations: conversation_id = conversation['uuid'] delete_id = self.delete_conversation(conversation_id) return True def upload_attachment(self, file_path): if file_path.endswith('.txt'): file_name = os.path.basename(file_path) file_size = os.path.getsize(file_path) file_type = "text/plain" with open(file_path, 'r', encoding='utf-8') as file: file_content = file.read() return { "file_name": file_name, "file_type": file_type, "file_size": file_size, "extracted_content": file_content } url = 'https://claude.ai/api/convert_document' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0', 'Accept-Language': 'en-US,en;q=0.5', 'Referer': 'https://claude.ai/chats', 'Origin': 'https://claude.ai', 'Sec-Fetch-Dest': 'empty', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'same-origin', 'Connection': 'keep-alive', 'Cookie': f'{self.cookie}', 'TE': 'trailers' } file_name = os.path.basename(file_path) content_type = self.get_content_type(file_path) files = { 'file': (file_name, open(file_path, 'rb'), content_type), 'orgUuid': (None, self.organization_id) } response = requests.post(url, headers=headers, files=files, impersonate="chrome110", proxies=self.proxies, timeout=self.timeout) if response.status_code == 200: return response.json() else: return False # Renames the chat conversation title def rename_chat(self, title, conversation_id): url = "https://claude.ai/api/rename_chat" payload = json.dumps({ "organization_uuid": f"{self.organization_id}", "conversation_uuid": f"{conversation_id}", "title": f"{title}" }) headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0', 'Accept-Language': 'en-US,en;q=0.5', 'Content-Type': 'application/json', 'Referer': 'https://claude.ai/chats', 'Origin': 'https://claude.ai', 'Sec-Fetch-Dest': 'empty', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'same-origin', 'Connection': 'keep-alive', 'Cookie': f'{self.cookie}', 'TE': 'trailers' } response = requests.post(url, headers=headers, data=payload, impersonate="chrome110", proxies=self.proxies, timeout=self.timeout) if response.status_code == 200: return True else: return False
many thanks,and the author update the 1.0.16 version,could fix this problem~