There are two large differences:

  1. The PHP code posts a field named file, your Python code posts a field named bulk_test2.mov.

  2. Your Python code posts an empty file. There Content-Length header is 160 bytes, exactly the amount of space the multipart boundaries and Content-Disposition part header take up. Either the bulk_test2.mov file is indeed empty, or you tried to post the file multiple times without rewinding or reopening the file object.

To fix the first problem, use 'file' as the key in your files dictionary:

files = {'file': open('bulk_test2.mov', 'rb')}
response = requests.post(url, files=files)

I used just the open file object as the value; requests will get the filename directly from the file object in that case.

The second issue is something only you can fix. Make sure you don't reuse files when repeatedly posting. Reopen, or use files['file'].seek(0) to rewind the read position back to the start.

The Expect: 100-continue header is an optional client feature that asks the server to confirm that the body upload can go ahead; it is not a required header and any failure to post your file object is not going to be due to requests using this feature or not. If an HTTP server were to misbehave if you don't use this feature, it is in violation of the HTTP RFCs and you'll have bigger problems on your hands. It certainly won't be something requests can fix for you.

If you do manage to post actual file data, any small variations in Content-Length are due to the (random) boundary being a different length between Python and PHP. This is normal, and not the cause of upload problems, unless your target server is extremely broken. Again, don't try to fix such brokenness with Python.

However, I'd assume you overlooked something much simpler. Perhaps the server blacklists certain User-Agent headers, for example. You could clear some of the default headers requests sets by using a Session object:

files = {'file': open('bulk_test2.mov', 'rb')}
session = requests.Session()
del session.headers['User-Agent']
del session.headers['Accept-Encoding']
response = session.post(url, files=files)

and see if that makes a difference.

If the server fails to handle your request because it fails to handle HTTP persistent connections, you could try to use the session as a context manager to ensure that all session connections are closed:

files = {'file': open('bulk_test2.mov', 'rb')}
with requests.Session() as session:
    response = session.post(url, files=files, stream=True)

and you could add:

response.raw.close()

for good measure.

Answer from Martijn Pieters on Stack Overflow
Top answer
1 of 1
6

There are two large differences:

  1. The PHP code posts a field named file, your Python code posts a field named bulk_test2.mov.

  2. Your Python code posts an empty file. There Content-Length header is 160 bytes, exactly the amount of space the multipart boundaries and Content-Disposition part header take up. Either the bulk_test2.mov file is indeed empty, or you tried to post the file multiple times without rewinding or reopening the file object.

To fix the first problem, use 'file' as the key in your files dictionary:

files = {'file': open('bulk_test2.mov', 'rb')}
response = requests.post(url, files=files)

I used just the open file object as the value; requests will get the filename directly from the file object in that case.

The second issue is something only you can fix. Make sure you don't reuse files when repeatedly posting. Reopen, or use files['file'].seek(0) to rewind the read position back to the start.

The Expect: 100-continue header is an optional client feature that asks the server to confirm that the body upload can go ahead; it is not a required header and any failure to post your file object is not going to be due to requests using this feature or not. If an HTTP server were to misbehave if you don't use this feature, it is in violation of the HTTP RFCs and you'll have bigger problems on your hands. It certainly won't be something requests can fix for you.

If you do manage to post actual file data, any small variations in Content-Length are due to the (random) boundary being a different length between Python and PHP. This is normal, and not the cause of upload problems, unless your target server is extremely broken. Again, don't try to fix such brokenness with Python.

However, I'd assume you overlooked something much simpler. Perhaps the server blacklists certain User-Agent headers, for example. You could clear some of the default headers requests sets by using a Session object:

files = {'file': open('bulk_test2.mov', 'rb')}
session = requests.Session()
del session.headers['User-Agent']
del session.headers['Accept-Encoding']
response = session.post(url, files=files)

and see if that makes a difference.

If the server fails to handle your request because it fails to handle HTTP persistent connections, you could try to use the session as a context manager to ensure that all session connections are closed:

files = {'file': open('bulk_test2.mov', 'rb')}
with requests.Session() as session:
    response = session.post(url, files=files, stream=True)

and you could add:

response.raw.close()

for good measure.

Top answer
1 of 3
2

As Mark Ma mentioned, you can get it done without leaving the standard library by utilizing urllib2. I like to use Requests, so I cooked this up:

import os
import requests

dump_directory = os.path.join(os.getcwd(), 'mp3')
os.makedirs(dump_directory, exist_ok=True)


def dump_mp3_for(resource):
    payload = {
        'api': 'advanced',
        'format': 'JSON',
        'video': resource
    }
    initial_request = requests.get('http://youtubeinmp3.com/fetch/', params=payload)
    if initial_request.status_code == 200:  # good to go
        download_mp3_at(initial_request)


def download_mp3_at(initial_request):
    j = initial_request.json()
    filename = '{0}.mp3'.format(j['title'])
    r = requests.get(j['link'], stream=True)
    with open(os.path.join(dump_directory, filename), 'wb') as f:
        print('Dumping "{0}"...'.format(filename))
        for chunk in r.iter_content(chunk_size=1024):
            if chunk:
                f.write(chunk)
                f.flush()

It's then trivial to iterate over a list of YouTube video links and pass them into dump_mp3_for() one-by-one.

for video in ['http://www.youtube.com/watch?v=i62Zjga8JOM']:
    dump_mp3_for(video)
2 of 3
1

In its API Doc, it provides one version of URL which returns download link as JSON: http://youtubeinmp3.com/fetch/?api=advanced&format=JSON&video=http://www.youtube.com/watch?v=i62Zjga8JOM

Ok Then we can use urllib2 to call the API and fetch API result, then unserialize with json.loads(), and download mp3 file using urllib2 again.

import urllib2
import json

r = urllib2.urlopen('http://youtubeinmp3.com/fetch/?api=advanced&format=JSON&video=http://www.youtube.com/watch?v=i62Zjga8JOM')
content = r.read()
# extract download link
download_url = json.loads(content)['link']
download_content = urllib2.urlopen(download_url).read()
# save downloaded content to file
f = open('test.mp3', 'wb')
f.write(download_content)
f.close()

Notice the file should be opened using mode 'wb', otherwise the mp3 file cannot be played correctly. If the file is big, downloading will be a time-consuming progress. And here is a post describes how to display downloading progress in GUI (PySide)

Discussions

Using requests.get() in python to view video - Stack Overflow
Please provide a valid video example to your code. Also add more context related to the problem of requesting and playing this video. ... If you would like to make to the progress bar (I don't know what it is named, hope you can understand) to move on, you just need to post some data to the server. More on stackoverflow.com
🌐 stackoverflow.com
error when trying to send a video using requests library Python - Stack Overflow
I'm encountering an error code: 400 when trying to post a video file. ... 400 Bad Request b'{ "ok":false, "error_code":400, "description":"Bad Request: there is no video in the request" }' More on stackoverflow.com
🌐 stackoverflow.com
Help with python-requests

Requests should do what you want:

>>> r = requests.post('https://io.cimediacloud.com/upload', files={'video.mp4': open('files/video.mp4', 'rb')})

http://docs.python-requests.org/en/latest/user/quickstart/#post-a-multipart-encoded-file

More on reddit.com
🌐 r/learnpython
9
5
July 22, 2014
http - how to input data via a post request using requests in python - Stack Overflow
0 I want to know about http://en.savefrom.net/1-how-to-download-youtube-video/ how it force video to download · 2 How to make a post request with REQUESTS package for Python? More on stackoverflow.com
🌐 stackoverflow.com
🌐
Stack Overflow
stackoverflow.com › questions › 57869954 › how-to-post-an-mp4-using-python-requests
How to POST an MP4 using Python requests? - Stack Overflow
def getresponse: userpass = b64encode(b"<username>:<password>").decode("ascii") headers = {'Content-type':'video/mp4', 'Authorization': 'Basic ' + userpass} files = {'file': open(file_path, 'rb')} response = requests.post(URL, files=files, headers=headers) return response
🌐
api.video
api.video › blog › tutorials › upload-a-big-video-file-using-python
Upload a big video file using Python
If you try to upload big files in Python, a common way to handle them is by breaking them into chunks. This tutorial will show you how to break your file into chunks and send the file for upload to api.video. ... If you have a large video you need to upload, sometimes the server you're uploading to will not accept it in one request.
🌐
api.video
api.video › blog › tutorials › upload-a-video-from-your-computer-with-the-api-video-api-python
Upload a video with api.video’s API (Python)
February 9, 2021 - response = requests.request("POST", ... up the endpoint you'll upload your video to, which is composed of https://ws.api.video/videos + / + videoId + /source....
🌐
Stack Overflow
stackoverflow.com › questions › 58027591 › using-requests-get-in-python-to-view-video
Using requests.get() in python to view video - Stack Overflow
Once you are in someone's websites, you can find out your browser keeps posting data to this target url every several seconds. Personally speaking, I think it is a tool to record the number of users watching in this room. For https://browser.events.data.microsoft.com/OneCollector/1.0/ this part, we shall have the same url, but the residual should be generated by the contents in your requests headers.
🌐
Stack Overflow
stackoverflow.com › questions › 57199396 › error-when-trying-to-send-a-video-using-requests-library-python › 57200237
error when trying to send a video using requests library Python - Stack Overflow
def sendVideo(bot_token,bot_chatID): url = "https://api.telegram.org/bot"+ bot_token +"/sendVideo"; files = {'file': open('C:/Users/myUser/Desktop/telegram/t_video.mp4', 'rb')} data = {'chat_id' : bot_chatID} r = requests.post(url, files=files) print(r.status_code, r.reason, r.content) python ·
Find elsewhere
🌐
Reddit
reddit.com › r/learnpython › help with python-requests
r/learnpython on Reddit: Help with python-requests
July 22, 2014 -

Help! I've been trying to upload a file in Python, but the API server keeps returning a "MissingOrInvalidFileName" error. I am porting Java code over to Python, so I know the API call works, at least in Java. What is different about these two HTTP requests that is causing the problem?

Java uploads fine:

private String uploadAssetAsSinglePartHttp(String fileName, String workspaceId, String  
folderId) throws ClientProtocolException, IOException {

    HttpClient client = buildAuthorizedClient();

    //Set up post
    String url = "https://io.cimediacloud.com/upload";
    HttpPost request = new HttpPost(url);

    //add file to request
    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    File video = new File("files/"+fileName);
    builder.addPart("file", new FileBody(video));

    //folder info in json
    JsonObject fileInfo = new JsonObject();
    if(workspaceId != null) {
        fileInfo.addProperty("workspaceId", workspaceId);
    }
    if(folderId != null)    {
        fileInfo.addProperty("folderId", folderId);
    }
    String fileJson = gson.toJson(fileInfo);
    builder.addTextBody("metadata", fileJson);

    //add json to request
    HttpEntity entity = builder.build();
    request.setEntity(entity);


    //execute request
    HttpResponse response = null;
    try {
        response = client.execute(request);
        System.out.println(response.getStatusLine().getReasonPhrase());
        return getResponseJsonProperty(response, "assetId");

    } catch (IOException e) {
        e.printStackTrace();
    } finally   {
        request.releaseConnection();
    }

    return null;

}

Python MissingOrInvalidFileName Error:

def upload_singlepart(folder_id=None):
    url = 'https://io.cimediacloud.com/upload'

    files = {'file': ('video.mp4', open('files/video.mp4', 'rb')),}
    metadata = {
        'workspaceId': your_workspace_id,
        'folderId': folder_id
    }
    data = {'metadata': json.dumps(metadata)}
    r = session.post(url, files=files, data=data)

    return r.json()['assetId']

If it helps, here is the cURL equivalent.

curl -XPOST -i "https://io.cimediacloud.com/upload" \
-H "Authorization: Bearer ACCESS_TOKEN" \
-F filename=@Movie.mov
-F metadata="{'workspaceId' : 'a585b641a60843498543597d16ba0108', 'folderId' : 
'a585b641a60843498543597d16ba0108' }"

Note: the metadata is optional, but i want to send it along with the file.

I'm about to switch to urllib3 for more detailed control over my requests -_- but first, I'll ask you guys. Thanks much.

P.S. I hear people talking about requests-toolbelt. Would that help? Thanks.

🌐
W3Schools
w3schools.com › python › ref_requests_post.asp
Python Requests post Method
A requests.Response object. ... If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail: sales@w3schools.com · If you want to report an error, or if you want to make a suggestion, send us an e-mail: help@w3schools.com · HTML Tutorial CSS Tutorial JavaScript Tutorial How To Tutorial SQL Tutorial Python Tutorial W3.CSS Tutorial Bootstrap Tutorial PHP Tutorial Java Tutorial C++ Tutorial jQuery Tutorial
🌐
Stack Overflow
stackoverflow.com › questions › 65443895 › how-to-input-data-via-a-post-request-using-requests-in-python
http - how to input data via a post request using requests in python - Stack Overflow
<input type="text" name="sf_url" value="" autofocus="" placeholder="Paste your video link here" onfocus="if(this.value &amp;&amp; this.select){this.select()}" id="sf_url"> ... import requests payload = {"sf_url": "https://www.youtube.com/watch?v=jNQXAC9IVRw&vl=en"} response = requests.post("https://en.savefrom.net/1-youtube-video-downloader-4/", payload) print(response.text)
🌐
Stack Overflow
stackoverflow.com › questions › 65734627 › is-it-possible-to-read-a-video-from-post-request-into-python-ffmpeg-or-opencv
Is it possible to read a Video from POST request into python-ffmpeg or OpenCV? - Stack Overflow
January 15, 2021 - The first thing is: give full confidence to the user by asking to enter the size of the video file (BAD IDEA). The second is: read the HEADER of the HTTP POST REQUEST "content-length: value" (this value can be also falsified by the user).
🌐
Real Python
realpython.com › python-requests
Python's Requests Library (Guide) – Real Python
July 23, 2025 - You make a GET request in Python using requests.get() with the desired URL. To add headers to requests, pass a dictionary of headers to the headers parameter in your request. To send POST data, use the data parameter for form-encoded data or the json parameter for JSON data.
🌐
Google
developers.google.com › youtube › developer's guide: python
Developer's Guide: Python | YouTube | Google for Developers
August 28, 2025 - The Using community features section describes API functions that allow your users to interact with YouTube videos. These functions explain requests for posting a rating, comment, or complaint to an existing video.
🌐
ReqBin
reqbin.com › code › python › ighnykth › python-requests-post-example
How do I send a POST request using Python Requests Library?
To send a POST request using the Python Requests Library, you should call the requests.post() method and pass the target URL as the first parameter and the POST data with the data= parameter.
🌐
Stack Abuse
stackabuse.com › how-to-upload-files-with-pythons-requests-library
How to Upload Files with Python's requests Library
September 19, 2021 - In this article, we learned how to upload files in Python using the requests library. Where it's a single file or multiple files, only a few tweaks are needed with the post() method.
🌐
Stack Overflow
stackoverflow.com › questions › 65080391 › how-does-posting-work-with-requests-in-python
post - How does posting work with `requests` in python? - Stack Overflow
November 30, 2020 - from requests_html import HTMLSession from bs4 import BeautifulSoup from requests import get def grabpost(ld, new={}): # Create dict then grab key from 'server40' [new.update({x[0]:x[1]}) for x in ld]; return new.get("40") def grabhtml(session, url): # Auto requests_html for html/js only res = session.get(url); res.html.render(); session.close(); return res AJAX = "https://www12.9anime.to/ajax/user/watching" URL = "https://www12.9anime.to/watch/descending-stories-showa-genroku-rakugo-shinju.xojv/ep-2" headers = {"content-type": "application/json"} TYPE = URL.rsplit(".")[-1].split("/")[0] ### G
🌐
Scrapfly
scrapfly.io › blog › posts › how-to-python-requests-post
Guide to Python requests POST method - Scrapfly Blog
November 5, 2024 - Discover how to use Python's requests library for POST requests, including JSON, form data, and file uploads, along with response handling tips.
🌐
TutorialsPoint
tutorialspoint.com › requests › requests_file_upload.htm
File Upload with Requests in Python
import requests myurl = 'https://httpbin.org/post' files = {'file': open('test.txt', 'rb')} getdata = requests.post(myurl, files=files) print(getdata.text) File upload test using Requests · E:\prequests>python makeRequest.py { "args": {}, "data": "", "files": { "file": "File upload test using Requests" }, "form": {}, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Content-Length": "175", "Content-Type": "multipart/form-data; boundary=28aee3a9d15a3571fb80d4d2a94bfd33", "Host": "httpbin.org", "User-Agent": "python-requests/2.22.0" }, "json": null, "origin": "117.223.63.135, 117.223.63.135", "url": "https://httpbin.org/post" } It is also possible to send the contents of the file as shown below− ·
🌐
AnyIP
anyip.io › blog › python-requests-post
How to make a POST with the Python Requests module?
The POST HTTP method is used when you want to send data inside the request's body. The post(…) function sends an HTTP request with the POST method.
🌐
Google
developers.google.com › youtube › data api › upload a video
Upload a Video | YouTube Data API | Google for Developers
When uploading test videos, you may want to specify a --privacyStatus argument value to ensure that those videos are private or unlisted. Valid values are public, private, and unlisted. ... #!/usr/bin/python import httplib import httplib2 import os import random import sys import time from apiclient.discovery import build from apiclient.errors import HttpError from apiclient.http import MediaFileUpload from oauth2client.client import flow_from_clientsecrets from oauth2client.file import Storage from oauth2client.tools import argparser, run_flow # Explicitly tell the underlying HTTP transport library not to retry, since # we are handling retry logic ourselves.