ftplib module
Overview
ftplib is Python’s standard library for interacting with FTP (File Transfer Protocol) servers. It handles the FTP protocol’s command-response pattern, letting you connect to servers, navigate directory trees, upload and download files, and manage passive/active modes. For most modern use cases involving file transfers, you might reach for paramiko (SFTP/SCP) or cloud storage SDKs instead — but for plain anonymous or credential-based FTP, ftplib gets the job done without extra dependencies.
Connection
Basic anonymous connection
from ftplib import FTP
ftp = FTP("ftp.example.com")
ftp.login() # anonymous login with empty user/pass
print(ftp.getwelcome())
Connecting with credentials
from ftplib import FTP
ftp = FTP("ftp.example.com")
ftp.login(user="alice", passwd="secret123")
# or:
ftp.connect("ftp.example.com", 21)
ftp.login(user="alice", passwd="secret123")
Context manager (Python 3.2+)
from ftplib import FTP
with FTP("ftp.example.com") as ftp:
ftp.login(user="alice", passwd="secret123")
print(ftp.pwd())
# Connection closes automatically
Using TLS (FTPS)
from ftplib import FTP_TLS
with FTP_TLS("ftp.example.com") as ftp:
ftp.login(user="alice", passwd="secret123")
ftp.prot_p() # switch to protected data channel
print(ftp.pwd())
Navigating Directories
ftp.pwd() # current directory
ftp.cwd("/pub/incoming") # change directory
ftp.retrlines("LIST") # list files as text
ftp.dir() # same as retrlines("LIST")
Listing files
# Simple listing
ftp.retrlines("LIST")
# Detailed listing
ftp.retrlines("LIST -la")
# Use nlst for just filenames
files = ftp.nlst()
print(files) # ['file1.txt', 'subdir', 'report.pdf']
Downloading Files
Text mode (retrlines)
from ftplib import FTP
with FTP("ftp.example.com") as ftp:
ftp.login()
ftp.cwd("/pub/docs")
# Read into a list of strings
lines = []
ftp.retrlines("RETR readme.txt", lines.append)
print("\n".join(lines))
Binary mode (retrbinary)
with FTP("ftp.example.com") as ftp:
ftp.login()
ftp.cwd("/pub/images")
with open("photo.jpg", "wb") as f:
ftp.retrbinary("RETR photo.jpg", f.write)
Download with progress tracking
def track_progress(data, f):
f.write(data)
print(".", end="", flush=True)
with FTP("ftp.example.com") as ftp:
ftp.login()
with open("largefile.zip", "wb") as f:
ftp.retrbinary("RETR largefile.zip", lambda d: track_progress(d, f))
Uploading Files
Binary upload (storbinary)
with FTP("ftp.example.com") as ftp:
ftp.login()
ftp.cwd("/pub/incoming")
with open("upload.txt", "rb") as f:
ftp.storbinary("STOR upload.txt", f)
Text upload (storlines)
lines = ["First line", "Second line", "Third line"]
with FTP("ftp.example.com") as ftp:
ftp.login()
ftp.cwd("/pub/incoming")
ftp.storlines("STOR notes.txt", lines)
Upload from a file object
with open("data.csv", "rb") as f:
with FTP("ftp.example.com") as ftp:
ftp.login()
ftp.storbinary("STOR data.csv", f)
Renaming and Deleting
ftp.rename("old_name.txt", "new_name.txt") # rename
ftp.delete("unwanted.txt") # delete file
ftp.mkd("/new_directory") # create directory
ftp.rmd("/empty_directory") # remove empty directory
Transfer Mode
FTP has two transfer modes that matter in ftplib:
Passive mode — The client tells the server which port to use for data transfer. This is the default in Python’s ftplib and works better through firewalls and NAT:
ftp = FTP("ftp.example.com")
ftp.login()
ftp.set_pasv(True) # explicitly enable passive (default)
Active mode — The server opens a connection back to the client. This can fail behind firewalls or NAT:
ftp.set_pasv(False) # disable passive = active mode
Error Handling
from ftplib import FTP, FTP_TLS, all_errors
import ftplib
try:
with FTP("ftp.example.com", timeout=10) as ftp:
ftp.login(user="alice", passwd="secret123")
files = ftp.nlst()
except ftplib.error_perm as e:
print(f"Permission error: {e}")
except ftplib.error_temp as e:
print(f"Temporary error (retry): {e}")
except ftplib.all_errors as e:
print(f"FTP error: {e}")
Common exceptions:
error_perm— 4xx errors (authentication failed, file not found)error_temp— 4xx transient errors (try again)error_proto— protocol-level errors
Downloading a File List with a Timeout
import ftplib
def fetch_filelist(ftp, dir_path):
ftp.cwd(dir_path)
files = []
ftp.retrlines("LIST", files.append)
return files
with FTP("ftp.example.com", timeout=30) as ftp:
ftp.login()
try:
file_list = fetch_filelist(ftp, "/pub")
for line in file_list:
print(line)
except ftplib.error_temp:
print("Server busy, try again later")
See Also
- /reference/modules/socket-module/ — lower-level socket networking
- /reference/modules/os-module/ — file and directory operations
- /tutorials/file-io/ — reading and writing files in Python