For secure file and data transfer, SFTP has long been a solid choice. It is efficient, widely used, and straightforward once you know how to work with it. Connecting to an SFTP server from Python takes a little more setup than using a desktop client, but it isn't difficult once the moving parts are clear.
In the guide below, we will connect to an SFTP server with Python, list files on the remote server, upload a file, download a file, and then run the full example as one script. If you are looking for a simple Python SFTP example to get started with automation, this is a good place to begin.
If you're specifically dealing with interrupted transfers, you may also want to read these related guides after this one:
How To Resume Interrupted SFTP Downloads In Python.
How To Resume Interrupted SFTP Uploads In Python.
If you also need a command line reference, see our SFTP commands cheat sheet.
Requirements for using SFTP with Python
Prior to jumping in, some setup is required. We’ll use the ‘pysftp’ package to connect and pass commands to the SFTP server. When you are ready to install it, manually run:
pip install pysftpOr create a requirements.txt file and declare your dependencies within. Then, save the following as requirements.txt:
pysftp>=0.2.9Then run:
pip install -r requirements.txtOnce that is done, we are ready to connect.
Connecting to SFTP with Python
In this post, we’ll be using an environment variable named SFTPTOGO_URL that contains all the information required to connect to an SFTP server using a URI format: sftp://user:password@host.
The variable is parsed to extract the URI parts using `urlparse`, and the remote server’s host key is verified by default using ~/.ssh/known_hosts.
Once the connection is established, the SFTP client object will be assigned to the variable: connection.
import pysftp
from urllib.parse import urlparse
import os
class Sftp:
def __init__(self, hostname, username, password, port=22):
"""Constructor Method"""
# Set connection object to None (initial value)
self.connection = None
self.hostname = hostname
self.username = username
self.password = password
self.port = port
def connect(self):
"""Connects to the sftp server and returns the sftp connection object"""
try:
# Get the sftp connection object
self.connection = pysftp.Connection(
host=self.hostname,
username=self.username,
password=self.password,
port=self.port,
)
except Exception as err:
raise Exception(err)
finally:
print(f"Connected to {self.hostname} as {self.username}.")
def disconnect(self):
"""Closes the sftp connection"""
self.connection.close()
print(f"Disconnected from host {self.hostname}")Listing files on an SFTP server with Python
Now that the connection is all set up, we can use it to list files on the remote SFTP server. This is achieved by calling the connection object’s listdir function or the listdir_attr function.
Either one of these functions can take a remote path argument or, if omitted, will list the files and directories in the current remote directory. The listdir function returns a list of filenames (as string), while the listdir_attr function returns a list of SFTPAttributes objects containing the file size, creation, modification timestamps and permissions, in addition to the file name.
In our example, our wrapper function returns a generator, allowing the function caller to iterate over the returned files.
def listdir(self, remote_path):
"""lists all the files and directories in the specified path and returns them"""
for obj in self.connection.listdir(remote_path):
yield obj
def listdir_attr(self, remote_path):
"""lists all the files and directories (with their attributes) in the specified path and returns them"""
for attr in self.connection.listdir_attr(remote_path):
yield attrUploading a file to SFTP with Python
The next step is to upload a file. Use the connection object’s put function and pass the path to the local file and the remote path, which is also where the file should end up by the end of the upload. The function call would look like: connection.put("./local.txt", "./remote.txt")
def upload(self, source_local_path, remote_path):
"""
Uploads the source files from local to the sftp server.
"""
try:
print(
f"uploading to {self.hostname} as {self.username} [(remote path: {remote_path});(source local path: {source_local_path})]"
)
# Download file from SFTP
self.connection.put(source_local_path, remote_path)
print("upload completed")
except Exception as err:
raise Exception(err)That covers a basic Python SFTP upload. If your real use case involves large files or unstable connections, the newer upload guide below is worth reading next because it deals with interrupted transfers:
How To Resume Interrupted SFTP Uploads In Python.
Downloading a file from SFTP with Python
The last job left for us to complete is downloading our files. Use the connection object’s get function, and pass the path to the remote file and the local path, where you would store the downloaded file. You would call the function like so: connection.get("./remote.txt", "./download.txt")
def download(self, remote_path, target_local_path):
"""
Downloads the file from remote sftp server to local.
Also, by default extracts the file to the specified target_local_path
"""
try:
print(
f"downloading from {self.hostname} as {self.username} [(remote path : {remote_path});(local path: {target_local_path})]"
)
# Create the target directory if it does not exist
path, _ = os.path.split(target_local_path)
if not os.path.isdir(path):
try:
os.makedirs(path)
except Exception as err:
raise Exception(err)
# Download from remote sftp server to local
self.connection.get(remote_path, target_local_path)
print("download completed")
except Exception as err:
raise Exception(err)This example also creates the target directory if it does not already exist, which makes the method a little more practical for simple scripts.
If you need to deal with dropped sessions or partially transferred files, read the related guide here:
How To Resume Interrupted SFTP Downloads In Python.
The whole Python SFTP example
So we’ve made it to the finish line! If you would like to run the entire program from start to finish, copy the following code and save it as main.py:
import pysftp
from urllib.parse import urlparse
import os
class Sftp:
def __init__(self, hostname, username, password, port=22):
"""Constructor Method"""
# Set connection object to None (initial value)
self.connection = None
self.hostname = hostname
self.username = username
self.password = password
self.port = port
def connect(self):
"""Connects to the sftp server and returns the sftp connection object"""
try:
# Get the sftp connection object
self.connection = pysftp.Connection(
host=self.hostname,
username=self.username,
password=self.password,
port=self.port,
)
except Exception as err:
raise Exception(err)
finally:
print(f"Connected to {self.hostname} as {self.username}.")
def disconnect(self):
"""Closes the sftp connection"""
self.connection.close()
print(f"Disconnected from host {self.hostname}")
def listdir(self, remote_path):
"""lists all the files and directories in the specified path and returns them"""
for obj in self.connection.listdir(remote_path):
yield obj
def listdir_attr(self, remote_path):
"""lists all the files and directories (with their attributes) in the specified path and returns them"""
for attr in self.connection.listdir_attr(remote_path):
yield attr
def download(self, remote_path, target_local_path):
"""
Downloads the file from remote sftp server to local.
Also, by default extracts the file to the specified target_local_path
"""
try:
print(
f"downloading from {self.hostname} as {self.username} [(remote path : {remote_path});(local path: {target_local_path})]"
)
# Create the target directory if it does not exist
path, _ = os.path.split(target_local_path)
if not os.path.isdir(path):
try:
os.makedirs(path)
except Exception as err:
raise Exception(err)
# Download from remote sftp server to local
self.connection.get(remote_path, target_local_path)
print("download completed")
except Exception as err:
raise Exception(err)
def upload(self, source_local_path, remote_path):
"""
Uploads the source files from local to the sftp server.
"""
try:
print(
f"uploading to {self.hostname} as {self.username} [(remote path: {remote_path});(source local path: {source_local_path})]"
)
# Download file from SFTP
self.connection.put(source_local_path, remote_path)
print("upload completed")
except Exception as err:
raise Exception(err)
if __name__ == "__main__":
sftp_url = os.environ.get("SFTPTOGO_URL")
if not sftp_url:
print("First, please set environment variable SFTPTOGO_URL and try again.")
exit(0)
parsed_url = urlparse(sftp_url)
sftp = Sftp(
hostname=parsed_url.hostname,
username=parsed_url.username,
password=parsed_url.password,
)
# Connect to SFTP
sftp.connect()
# Lists files with attributes of SFTP
path = "/"
print(f"List of files with attributes at location {path}:")
for file in sftp.listdir_attr(path):
print(file.filename, file.st_mode, file.st_size, file.st_atime, file.st_mtime)
# Upload files to SFTP location from local
local_path = "/Users/saggi/Downloads/tls2.png"
remote_path = "/tls2.png"
sftp.upload(local_path, remote_path)
# Lists files of SFTP location after upload
print(f"List of files at location {path}:")
print([f for f in sftp.listdir(path)])
# Download files from SFTP
sftp.download(
remote_path, os.path.join(remote_path, local_path + '.backup')
)
# Disconnect from SFTP
sftp.disconnect()Finally, run it using the command:
python main.py
Congratulations on connecting to SFTP using Python.
From here, you can build on this example for larger automation workflows, scheduled jobs, or more resilient transfer routines.
Use cases for this guide
This example is useful if you want to:
- Connect to an SFTP server from Python
- List files and inspect file attributes
- Upload a file with Python over SFTP
- Download a file with Python over SFTP
- Start building simple SFTP automation
If you need retry logic or resumable transfers, the two newer Python guides linked above are the better next step.
Check out more code samples on Github. Explore SFTP automation to reduce human error and streamline workflows.
Frequently asked questions
Can Python connect to an SFTP server?
Yes. Python can connect to an SFTP server by using an SFTP-capable library. In this example, the connection is made with pysftp, which handles the session and lets you list files, upload files, and download files.
How do I upload a file to SFTP with Python?
You can upload a file by using the connection object’s put function and passing the local file path and remote destination path. In this article, the upload step is wrapped in a simple method for clarity.
How do I download a file from SFTP with Python?
You can download a file by using the connection object’s get function and passing the remote file path and the local destination path. This post also shows how to create the target directory if it does not already exist.
How do I list files on an SFTP server in Python?
You can list files with listdir if you only need names, or listdir_attr if you also need file metadata such as size, timestamps, and permissions.
Can I resume interrupted SFTP transfers in Python?
Yes, but not with the simple example in this post. For that, read these two related guides:
https://sftptogo.com/blog/resume-interrupted-sftp-downloads-python/
https://sftptogo.com/blog/how-to-resume-isftp-uploads-python/
Where can I find common SFTP commands?
You can find a practical command reference here:
https://sftptogo.com/blog/sftp-commands-cheat-sheet/
