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)
Answer from Michael Blakeley on Stack Overflow
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)

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.

Discussions

How to POST an MP4 using Python requests? - Stack Overflow
I am trying to upload an MP4 file, using requests.post. I'm not sure if it is due to the size of the file, as it is 3.2MB and I have seen people saying they have issues over 1.5MB. Any help is 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
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
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
🌐
Codegive
codegive.com › blog › python_requests_videos.php
Python Requests Videos (2026): Master Web Data & Automate Anything – Unlock the Web's True Potential!
2 weeks ago - Explanation: This example illustrates a POST request, common for sending data to an API. headers: Used to pass authentication tokens (like Bearer API_KEY) and specify the Content-Type of the request body (e.g., application/json). json=payload: requests handles converting the Python dictionary payload into a JSON string and setting the correct Content-Type header.
🌐
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 › 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
🌐
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.
🌐
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
🌐
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.
🌐
Scrapfly
scrapfly.io › blog › posts › how-to-python-requests-post
Guide to Python requests POST method - Scrapfly Blog
1 week ago - Discover how to use Python's requests library for POST requests, including JSON, form data, and file uploads, along with response handling tips.
🌐
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)
🌐
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.
🌐
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).
🌐
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.
🌐
TutorialsPoint
tutorialspoint.com › requests › requests_file_upload.htm
Requests - File Upload
import requests myurl = 'https://httpbin.org/post' files = {'file': open('test.txt', 'rb')} getdata = requests.post(myurl, files=files) print(getdata.text) ... 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" }
🌐
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.
🌐
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
🌐
Tutorialspoint
tutorialspoint.com › python › python_requests_post_method.htm
Python Requests post() Method
The Python Requests post() method is used to send HTTP POST requests to a specified URL. It allows sending data to the server which is typically used for submitting forms or uploading files.