Using Webhooks with Python: Part 1

Today I’m going to share a tutorial about how to use Discord webhooks in python. While the specific example is Discord, the tutorial will show how we can use docs and software like postman to figure out how to use webhooks in general.

So, first things first, we need to get the URL of the webhook we want to connect to. In Discord, webhooks can be generated via channel settings by users with appropriate permissions. A guide on how to get a webhook can be found on here on Discord’s website. One important thing to note: there is no authentication required to make use of a channel’s webhook, so if your webhook falls into the wrong hands it can easily be misused. Be wary about sharing it to people you can’t trust.

The next step is to get code to use the webhook in a python script. We could just write some, but if we want to be lazy we can use Postman to do it for us. Postman is a tool that allows you to test interactions with webhooks and can give you sample code to copy those interactions in many different languages. First of all, we are just going to test our webhook so it’s working okay, to do this use Postman to send a GET command to the webhook. If successul, it will return a 200 OK status and give you some information about the attached channel:

Sample GET response from Postman

Sample GET response from Postman

So, now that we know it works, we want to make a webhook that actually does something. For this tutorial, we’ll make one that posts a message to the channel. According to the Discord webhook docs we need to send a POST command with a “content” parameter. To do this, we’re going to switch Postman to POST and add a key named “content” with the message we want to send to the body. Below you will see what to enter to have the message “further reading” sent to your channel:

Sample POST response from Postman

Sample POST response from Postman

If successful you will see the message “further reading” posted in your channel by the bot that represents your webhook. Now, >350 words into this python tutorial we will see our first python code! In Postman press the “code” button on the right hand side and select “Python http.client (Python 3) and something like the following will appear:

import http.client

conn = http.client.HTTPSConnection("discordapp.com")

payload = "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"content\"\r\n\r\nfurther reading\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--"

headers = {
    'content-type': "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW",
    'cache-control': "no-cache",
    'postman-token': "cf7dc5f7-c1bf-597c-6e74-2394d3aa3343"
    }

conn.request("POST", "YOUR WEBHOOK URL", payload, headers)

res = conn.getresponse()
data = res.read()

print(data.decode("utf-8"))

That is the python code you need to post the message “further reading” to your channel. Note: there is a second python option but it uses the urllibs3 library which can sometimes cause issues when freezing your scripts with pyinstaller.

Now, we don’t just want to post the same message to the same channel, we want to play around with this code a bit to allow us to send any text to any channel. So, we’re going to turn this into a function that takes two parameters “message” and “webhook.” For the message, you can look in the “payload” variable and find the “further reading” message we sent. payload = ...name=\"content\"\r\n\r\nfurther reading\r\n... We are going to rewrite the payload to send the message variable instead.

For the webhook URL, well the code above is already giving you a clue. On line 13 the second parameter in conn.request is a partial version of your Webhook URL. Note that while in this case it is a partial URL, if you put the full URL in there it will still work fine. So, here is the function version to allow that code send any message to any channel:

import http.client

def send(message, webhook):

    conn = http.client.HTTPSConnection("discordapp.com")

    payload = "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"content\"\r\n\r\n" + message + "\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--"

    headers = {
        'content-type': "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW",
        'cache-control': "no-cache",
        }

    conn.request("POST", webhook, payload, headers)

    res = conn.getresponse()
    data = res.read()

    print(data.decode("utf-8"))

There you have it, your very own Discord channel messaging function! You may notice that I have removed one of the headers; the “postman-token” header is part of a workaround for a bug in Postman so it isn’t needed in our code. You may also notice that each time you run this code that a blank line is printed to console, this is due to the print(data.decode("utf-8")) line which is printing a response from Discord. This response is usually blank but it will contain content in the case of an error.

Here is where part 1 of the tutorial ends. In part 2 we are going to go over how to handle hitting rate limits on your commands. In the mean time, have a look over the Discord webhook docs and try making functions to perform other webhook interactions.

This entry was posted in Python, tutorial and tagged , , , . Bookmark the permalink.

2 Responses to Using Webhooks with Python: Part 1

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.