Konrad Konrad - 2 months ago 31
Python Question

Python: curl -F equivalent with Requests or other

I want to reproduce the following curl -F request (from the Messenger API) to send an image file and parameters to Messenger's Send API:

curl \
-F recipient='{"id":"USER_ID"}' \
-F message='{"attachment":{"type":"image", "payload":{}}}' \
-F filedata=@/tmp/shirt.png \
"https://graph.facebook.com/v2.6/me/messages?access_token=PAGE_ACCESS_TOKEN"


I'm using Requests and I tried many, many things (including with correct recipient IDs, etc.. For instance:

recipient = '{"id":"USER_ID"}'
message = '{"attachment":{"type":"image", "payload":{}}}'
files = [("recipient", recipient), ("message", message), ("filedata", open(imagePath, 'rb'))]
r = requests.post('https://graph.facebook.com/v2.6/me/messages?access_token=ACCESS_TOKEN', files=files)


I also tried:

files = {"recipient" : recipient, "message" : message, "filedata" : open(imagePath, "rb")}


I almost always get this response error from Messenger:

'{"error":{"message":"(#100) param recipient must be non-empty.","type":"OAuthException","code":100,"fbtrace_id":"xxxxx"}}'


I'm at a loss here. I'm probably misusing the Requests syntax somehow, or sending a poorly formatted string to the API, but I've read the Requests documentation and browsed through StackOverflow's questions on this and couldn't solve my issue. Thank you.

Answer

I believe the issue is that you are trying to send formdata inside the requests file kwarg, when it should be in data:

data = {
    'recipient': '{"id":"USER_ID"}',
    'message': '{"attachment":{"type":"image", "payload":{}}}'
}
files = {
    "filedata": open(imagePath, 'rb')
}
r = requests.post('https://graph.facebook.com/v2.6/me/messages?access_token=ACCESS_TOKEN', data=data, files=files)

The one assumption is that imagePath exists.

Also in python {} denotes a Set if it doesn't have key:value pairs in it, so in your answer, you are passing a Set of a single tuple, which has two items in it, the string filedata and a file object.

{("filedata", open(imgName, 'rb'))} # Set of tuple
{"filedata": open(imgName, 'rb')}   # dictionary