I have implemented the following Python function according to the documentation https://github.com/tladesignz/bridgedb?tab=readme-ov-file#accessing-the-moat-interface:
import requests
MOAT_SERVER_URL = "https://bridges.torproject.org"
def request_bridges():
transports = ["obfs4"]
payload = {
"data": [{
"version": "0.1.0",
"type": "client-transports",
"supported": transports,
}]
}
headers = {
"Content-Type": "application/json"
}
response = requests.post(f"{MOAT_SERVER_URL}/moat/fetch", json=payload, headers=headers)
if response.status_code == 200:
json_data = response.json()
moat_data = json_data["data"][0] # <- Error
if "challenge" in moat_data:
# captcha_challenge(moat_data)
else:
pass # FIXME: Error Handling
else:
pass # FIXME: Error Handling
But the request does not seem to be correct because json_data has the following value:
{
"errors":[
{
"id":"0",
"type":"",
"version":"0.1.0",
"code":415,
"status":"Unsupported Media Type",
"detail":""
}
]
}
The code should request bridges for the user via BridgeDB, so that the user can then solve the captcha which should be present in moat_data. (Just like the Tor Browser does)
I have already tried to send the payload as data instead of json:
import requests
MOAT_SERVER_URL = "https://bridges.torproject.org"
def request_bridges():
transports = ["obfs4"]
payload = {
"data": [{
"version": "0.1.0",
"type": "client-transports",
"supported": transports,
}]
}
headers = {
"Content-Type": "application/x-www-form-urlencoded"
}
response = requests.post(f"{MOAT_SERVER_URL}/moat/fetch", data=payload, headers=headers)
# Rest of the code
I have also tried using Curl to check if the Python user agent might be blocked:
curl -X POST -H "Content-Type: application/json" -d '{"data": [{"version": "0.1.0", "type": "client-transports", "supported": ["obfs4"]}]}' https://bridges.torproject.org/moat/fetch
But this all returns the same JSON code as above.
As I found out myself, the BridgeDB uses the standard https://jsonapi.org/ which prescribes the content type "application/vnd.api+json".
Here is the correct code for this function:
import requests
MOAT_SERVER_URL = "https://bridges.torproject.org"
def request_bridges():
transports = ["obfs4"]
payload = {
"data": [{
"version": "0.1.0",
"type": "client-transports",
"supported": transports,
}]
}
headers = {
"Content-Type": "application/vnd.api+json"
}
response = requests.post(f"{MOAT_SERVER_URL}/moat/fetch", json=payload, headers=headers)
if response.status_code == 200:
json_data = response.json()
moat_data = json_data["data"][0]
if "challenge" in moat_data:
# captcha_challenge(moat_data)
else:
pass # FIXME: Error Handling
else:
pass # FIXME: Error Handling