Skip to content

Commit c0c2d96

Browse files
authored
Create server.py
1 parent 00e8047 commit c0c2d96

1 file changed

Lines changed: 156 additions & 0 deletions

File tree

server.py

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
import cloudscraper
2+
import time
3+
4+
from urllib.parse import unquote
5+
from flask import Flask, request, Response
6+
7+
scraper = cloudscraper.create_scraper(
8+
browser={
9+
'browser': 'chrome',
10+
'platform': 'windows',
11+
'desktop': True
12+
},
13+
delay=1,
14+
allow_brotli=True
15+
)
16+
17+
18+
def set_user_agent(headers):
19+
# this needs to match Sec-Ch-Ua (cloudflare will flag as a bot seeing two different user agents)
20+
# make sure to change it accordingly if you change this
21+
headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) ' \
22+
'Chrome/120.0.0.0 Safari/537.36'
23+
return headers
24+
25+
26+
def set_security_headers(headers):
27+
headers['Sec-Ch-Ua'] = '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"'
28+
headers['Sec-Ch-Ua-Mobile'] = '?0'
29+
headers['Sec-Ch-Ua-Platform'] = '"Windows"'
30+
headers['Sec-Fetch-Dest'] = 'empty'
31+
headers['Sec-Fetch-Mode'] = 'cors'
32+
headers['Sec-Fetch-Site'] = 'same-origin'
33+
return headers
34+
35+
36+
def set_origin_and_ref(headers, origin, ref):
37+
headers['Origin'] = origin
38+
headers['Referer'] = ref
39+
return headers
40+
41+
42+
def generate_origin_and_ref(url, headers):
43+
data = url.split('/')
44+
first = data[0]
45+
base = data[2]
46+
c_url = f"{first}//{base}/"
47+
headers = set_origin_and_ref(headers, c_url, c_url)
48+
return headers
49+
50+
51+
app = Flask(__name__)
52+
53+
HOP_BY_HOP_HEADERS = {
54+
'connection',
55+
'keep-alive',
56+
'proxy-authenticate',
57+
'proxy-authorization',
58+
'te',
59+
'trailers',
60+
'transfer-encoding',
61+
'upgrade',
62+
}
63+
64+
65+
def clean_headers(response):
66+
headers = {}
67+
for name, value in response.headers.items():
68+
if name.lower() not in HOP_BY_HOP_HEADERS:
69+
headers[name] = value
70+
headers.pop('content-encoding', None)
71+
headers.pop('content-length', None)
72+
return headers
73+
74+
75+
def generate_proxy_response(response) -> Response:
76+
content_type = response.headers.get('content-type', '')
77+
78+
if 'text' in content_type or 'html' in content_type:
79+
content = response.text
80+
else:
81+
content = response.content
82+
83+
headers = clean_headers(response)
84+
85+
# For JSON content
86+
if 'application/json' in content_type:
87+
return Response(content, status=response.status_code, content_type='application/json')
88+
89+
# For HTML content
90+
if 'text/html' in content_type:
91+
return Response(content, status=response.status_code, content_type='text/html; charset=utf-8')
92+
93+
# For all other content types
94+
return Response(
95+
content,
96+
status=response.status_code,
97+
headers=headers
98+
)
99+
100+
101+
def get_headers():
102+
headers = {
103+
'Accept': 'application/json, text/plain, */*',
104+
'Accept-Language': 'en-US,en;q=0.9',
105+
'Accept-Encoding': 'gzip, deflate, br',
106+
'Connection': 'keep-alive'
107+
}
108+
headers = set_user_agent(headers)
109+
headers = set_security_headers(headers)
110+
return headers
111+
112+
113+
def get_proxy_request_url(req, url):
114+
full_url = unquote(url.strip('"'))
115+
if req.query_string:
116+
full_url = f"{full_url}?{req.query_string.decode('utf-8')}"
117+
return full_url
118+
119+
120+
def get_proxy_request_headers(req, url):
121+
headers = get_headers()
122+
headers['Accept-Encoding'] = 'gzip, deflate, br'
123+
124+
for header in req.headers:
125+
if header[0].lower() not in ['host', 'connection', 'content-length']:
126+
headers[header[0]] = header[1]
127+
headers = generate_origin_and_ref(url, headers)
128+
return headers
129+
130+
131+
# Cloudflare bypassed request
132+
@app.route("/api/proxy/<path:url>", methods=["GET"])
133+
def handle_proxy(url):
134+
if request.method == 'GET':
135+
full_url = get_proxy_request_url(request, url) # parse request url
136+
headers = get_proxy_request_headers(request, url) # generate headers for the request
137+
138+
try:
139+
start = time.time()
140+
response = scraper.get(full_url, headers=headers)
141+
end = time.time()
142+
elapsed = end - start
143+
print(f"Proxied request for {full_url.split('?')[0]} in {elapsed:.6f} seconds")
144+
response.raise_for_status()
145+
146+
return generate_proxy_response(response)
147+
148+
except Exception as e:
149+
print(f"Proxy Request Error: {str(e)}")
150+
return {'error': str(e)}, 500
151+
152+
153+
if __name__ == "__main__":
154+
print('Starting cloudflare bypass proxy server')
155+
from waitress import serve
156+
serve(app, host="0.0.0.0", port=5000)

0 commit comments

Comments
 (0)