ibid
ibid

Reputation: 162

WebSocketProxyException 403 when trying to submit image with praw on pythonanywhere

I'm trying to use praw on pythonanywhere to natively upload an image to reddit.

praw.models.Subreddit.submit_image(title, image_path)

This works fine on my computer, but on pythonanywhere it throws a 403 error. (The image still gets uploaded though.)

I see on pythonanywhere's website that 403 errors are due to their proxy whitelist, but reddit is one of the whitelisted websites and praw uses requests which pythonanywhere says is a compatible library. Also the regular submit works fine.

File "/home/ibid/.local/lib/python3.7/site-packages/praw/models/reddit/subreddit.py", line 780, in submit_image
    return self._submit_media(data, timeout)
File "/home/ibid/.local/lib/python3.7/site-packages/praw/models/reddit/subreddit.py", line 494, in _submit_media
    response["json"]["data"]["websocket_url"], timeout=timeout
File "/home/ibid/.local/lib/python3.7/site-packages/websocket/_core.py", line 514, in create_connection
    websock.connect(url, **options)
File "/home/ibid/.local/lib/python3.7/site-packages/websocket/_core.py", line 223, in connect
    options.pop('socket', None))
File "/home/ibid/.local/lib/python3.7/site-packages/websocket/_http.py", line 122, in connect
    sock = _tunnel(sock, hostname, port, auth)
File "/home/ibid/.local/lib/python3.7/site-packages/websocket/_http.py", line 293, in _tunnel
    "failed CONNECT via proxy status: %r" % status)
websocket._exceptions.WebSocketProxyException: failed CONNECT via proxy status: 403

Upvotes: 1

Views: 615

Answers (1)

jarhill0
jarhill0

Reputation: 1629

I wrote the image-submit feature in PRAW. As is noted in the documentation, the Reddit API uses websockets when submitting images or videos through the API. This is different from how the API works for text or link submissions, which directly return the URL of the created post. When it comes to images and videos, the response is something like

{'json': {'data': {'user_submitted_page': 'https://www.reddit.com/user/username/submitted/',
                   'websocket_url': 'wss://ws-05ba9e4989f78959d.wss.redditmedia.com/rte_images/z4a98g21vsb31?m=AQAAHFs1XR-NRjAq9D4PPYA6SuDvFIMUGGv2Vpv5ePM2bLV6wf5o'},
          'errors': []}}

We then have to listen on the websocket URL to eventually get the url of the created post. If you're interested, the relevant code is here.


As you found, the websocket URLs (at least at the time of this answer) tend to be a subdomain of *.wss.redditmedia.com. redditmedia.com isn't on the PythonAnywhere whitelist (though reddit.com itself is), so the connection fails.

I see a few solutions for you, given here with what I think is most ideal first:

  1. Get Giles Thomas (who left a comment) or someone else from PythonAnywhere to whitelist subdomains of wss.redditmedia.com.
  2. In PRAW >=6.5.0, pass the parameter without_websockets=True to disable the use of websockets. As noted in the documentation of submit_image, setting this to True means that you won't get a return value at all.
  3. In PRAW <6.5.0, use a try-except block around every use of submit_image. As you discovered, the posts will still be created. However, you will not receive a Submission object as a return value because the websocket will fail.
  4. Pay to upgrade to the non-whitelisted version of PythonAnywhere.

Upvotes: 3

Related Questions