Python CGI Scripts
Python CGI scripts: headers, cgi.FieldStorage, and common patterns
How do you write a basic CGI script in Python?
A Python CGI script starts with #!/usr/bin/python3 (or the correct interpreter path for your host), imports cgi and sys, optionally calls cgi.enable_traceback() for debugging, then prints the Content-Type header and a blank line before any body output. Form data is read with cgi.FieldStorage(). The script needs execute permission (chmod 755) and must live in a CGI-enabled directory.
Python 2 vs Python 3 on shared hosting
Many older shared hosts default to Python 2 in the CGI path even if Python 3 is installed. If your shebang is #!/usr/bin/python3 and only Python 2 is at that path, the script fails with a 500. Run 'python --version' and 'python3 --version' in a shell session on your host to see what is available. Some hosts require #!/usr/bin/env python3 to find the version-3 binary in the PATH.
Python 2 reached end of life in 2020 and receives no security updates. If your host only offers Python 2 in the CGI path and you cannot install Python 3, that is a signal to find a different host or switch to a hosted form endpoint. Writing new CGI code in Python 2 in 2026 means inheriting known, unfixed vulnerabilities in the interpreter itself.
Reading form data with cgi.FieldStorage
import cgi; form = cgi.FieldStorage() parses both GET and POST requests, including multipart/form-data for file uploads. Access a field with form.getvalue('fieldname'), which returns the string value or None if the field is absent. For file upload fields, form['fieldname'] is a FieldStorage instance with a .file attribute you read from and a .filename attribute with the original filename.
The cgi module was deprecated in Python 3.11 and is scheduled for removal in a future version. For new projects, prefer a lightweight WSGI framework like Flask or Bottle that can run on a WSGI-capable host, which gives you proper request parsing without the CGI overhead. For existing CGI scripts that work and need maintenance, cgi.FieldStorage is fine to continue using for now.
Printing headers in Python
Python CGI scripts print headers to sys.stdout the same way as Perl: the Content-Type header, a blank line, then the body. The most common mistake is printing a blank line or any other output before the Content-Type, which garbles the response. sys.stdout.flush() after the headers ensures they are sent before the body, though Python typically flushes on newline in CGI mode.
For binary output (serving an image or PDF), set sys.stdout = sys.stdout.buffer (Python 3) before printing binary content, because Python 3's sys.stdout is a text stream by default. Alternatively, write to sys.stdout.buffer directly for the binary body while keeping sys.stdout for the headers.
What to know
Key points
- Confirm the Python 3 path on your host before writing Python 3 syntax. Some hosts default to Python 2; use 'python3 --version' in a shell to verify.
- The cgi module is deprecated in Python 3.11+. For new projects consider a lightweight WSGI framework; for maintenance, cgi.FieldStorage still works.
- Print Content-Type before any body output. Any output before the headers, including tracebacks, garbles the HTTP response.
- Use cgi.enable_traceback() during development. Routes Python tracebacks to the browser response body so you can read the actual error.
Get help
Listings and a local agent, when you are ready
Need a CGI script built, debugged, or a hosting environment configured? Forms use a clearly-marked placeholder endpoint until wired to a real system.
Reserved for an affiliate link to a vetted shared or VPS hosting provider that supports CGI and Perl/Python execution. Operator wires affiliate link here.
Self-hosted lead form for custom CGI development inquiries. Placeholder endpoint until wired to the operator's CRM or email handler.
Open inquiry form →Custom CGI development
Hosting setup help
Questions