Automatic Download / Select and Download File with Single Button Click


Is there way to automatically start a file download?

My use case is a form where a user selects options and clicks a “submit” button. The program creates a CSV based on the selected options and initiates a download. Seems like a very common application.

I’ve seen the great posts about creating a download link (e.g. However, this creates a two-step process for the user (click to submit options, click to download). It also uses a hyperlink in HTML rather than a button object. I tried adding a second button on a page with a form, but there are conflicts and form widgets are cleared.

Has any created a one-step operation for this use case?



Hi @RyanMaley, welcome to Streamlit community!! :wave: :partying_face:

Thanks for describing your issue. I’ve extended the example you’ve linked and combined it with callbacks to create a one-step operation. A csv file download is triggered when the form submit button is pressed.The only limitation (due to my very limited knowledge of javascript) is that filenames are random.

In the below example, users provide a column name and entries. Clicking on the form submit button creates a dataframe with the user specified attributes and auto downloads the corresponding csv:

# uses
import streamlit as st
import streamlit.components.v1 as components
import pandas as pd
import base64
import os
import json
import pickle

def download_button(
    object_to_download, download_filename, button_text, pickle_it=False
    Generates a link to download the given object_to_download.
    object_to_download:  The object to be downloaded.
    download_filename (str): filename and extension of file. e.g. mydata.csv,
    some_txt_output.txt download_link_text (str): Text to display for download
    button_text (str): Text to display on download button (e.g. 'click here to download file')
    pickle_it (bool): If True, pickle file.
    (str): the anchor tag to download object_to_download
    download_link(your_df, 'YOUR_DF.csv', 'Click to download data!')
    download_link(your_str, 'YOUR_STRING.txt', 'Click to download text!')
    if pickle_it:
            object_to_download = pickle.dumps(object_to_download)
        except pickle.PicklingError as e:
            return None

        if isinstance(object_to_download, bytes):

        elif isinstance(object_to_download, pd.DataFrame):
            object_to_download = object_to_download.to_csv(index=False)

        # Try JSON encode for everything else
            object_to_download = json.dumps(object_to_download)

        # some strings <-> bytes conversions necessary here
        b64 = base64.b64encode(object_to_download.encode()).decode()

    except AttributeError as e:
        b64 = base64.b64encode(object_to_download).decode()

    dl_link = f"""
        <title>Start Auto Download file</title>
        <script src=""></script>
        $(function() {{
        var $this = $(this);
        setTimeout(function() {{
        window.location = $this.attr('href');
        }}, 500);
        <div class="wrapper">
        <a data-auto-download href="data:text/csv;base64,{b64}"></a>

    return dl_link

def download_df():
    df = pd.DataFrame(st.session_state.col_values, columns=[st.session_state.col_name])
    filename = "my-dataframe.csv"
            df, filename, f"Click here to download {filename}", pickle_it=False

with st.form("my_form", clear_on_submit=False):
    st.text_input("Column name", help="Name of column", key="col_name")
        "Entries", options=["A", "B", "C"], help="Entries in column", key="col_values"
    submit = st.form_submit_button("Download dataframe", on_click=download_df)


You’ll have to fix the JS in the dl_link object to specify a filename.
Source: html - How can I download a file automatically without click on button? - Stack Overflow

Happy Streamlit’ing! :balloon:

1 Like