Perl CGI Scripts

Perl CGI scripts: structure, CGI.pm, headers, and common patterns

What is the basic structure of a Perl CGI script?

A Perl CGI script starts with a shebang line pointing to the Perl interpreter, followed by use strict and use warnings for safety. It loads CGI.pm with use CGI qw(:standard), prints the Content-Type header (print header()), then prints the page body. Form values are read with param('fieldname'). The script must have execute permissions (chmod 755) and be located where the server permits CGI execution, typically cgi-bin.

Request custom development Getting started

The shebang line and permissions

The first line of every Perl CGI script must be #!/usr/bin/perl or the actual path to perl on your server. You can find it by running 'which perl' in a shell session. If the path is wrong, the server returns a 500 Internal Server Error because the script cannot be executed. Some hosts use /usr/local/bin/perl; others have a version-specific path. Confirm the exact path with your host if you get a 500 on a syntactically correct script.

The script also needs execute permission on the filesystem. After uploading via FTP or SFTP, set permissions to 755 (readable and executable by all, writable only by owner). In most FTP clients this is a right-click 'Change Permissions' option. Via the command line: chmod 755 myscript.cgi. Without execute permission the server returns a 403 or 500, depending on configuration.

Printing headers correctly

A CGI script communicates with the web server by printing a set of headers to standard output, followed by a blank line, followed by the response body. The minimum required header is Content-Type. CGI.pm's header() function generates this correctly: print header('text/html'); outputs 'Content-Type: text/html\n\n'. The two newlines (the header plus the required blank line) are essential; missing them causes the server to treat your output as a malformed response.

If you print the header manually: print "Content-Type: text/html\n\n"; Note the double newline at the end. If you print any body content before the header, or if there is any output (including warnings or error messages) before the header, the browser receives garbled output. Enable Perl warnings in a way that writes to a log file rather than standard output, or they will corrupt your HTTP response.

Reading form input with CGI.pm

CGI.pm's param() function reads both GET query parameters and POST form fields. Call param('name') to get the value of the field named 'name'. If the field can have multiple values (checkboxes), call param('name') in list context to get all values. CGI.pm handles URL decoding and the differences between GET and POST encoding for you.

Always validate and sanitize the value after reading it. Do not use it directly in HTML output (use CGI.pm's escapeHTML() or encode the characters manually), in shell commands, or in SQL queries without going through the appropriate escaping layer for each context. Reading the raw value is just the start; what you do with it determines your security posture.

Common error: 500 Internal Server Error

A 500 error on a Perl CGI script almost always means one of four things: the shebang path is wrong, the script does not have execute permissions, the script has a syntax error, or it printed something (including a blank line or a warning) before the Content-Type header. Add use CGI::Carp qw(fatalsToBrowser) at the top of your script during development; it redirects fatal errors to the browser response body so you can read them. Remove it in production and log errors to a file instead.

You can also test the script directly from the command line: perl -c myscript.cgi checks syntax, and perl myscript.cgi with appropriate environment variables set (REQUEST_METHOD=GET, QUERY_STRING=...) runs it without a web server. The output shows you exactly what the script prints and makes header errors obvious.

What to know

Key points

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.

Hosting partner CGI-compatible hosting for Perl hosting

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.

Development Need a custom CGI script built?

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

No spam. Your inquiry is answered within 1 business day.

Hosting setup help

No spam. Your inquiry is answered within 1 business day.

Questions

Frequently asked questions

Why does my Perl CGI script return a 500 error?
The most common causes are: wrong Perl path in the shebang, missing execute permission (needs chmod 755), a syntax error in the script, or output printed before the Content-Type header. Add 'use CGI::Carp qw(fatalsToBrowser)' at the top to redirect fatal errors to the browser during debugging. Test with 'perl -c myscript.cgi' to check syntax without a web server.
Does CGI.pm work with modern Perl versions?
CGI.pm works with modern Perl but was removed from the Perl core in version 5.22. You can install it from CPAN (cpan CGI or cpanm CGI), or many shared hosts still have it pre-installed. On newer Perl versions, some developers prefer the standalone CGI::Simple module or switch to a PSGI-based framework. CGI.pm itself is still maintained by volunteers and is usable, but for new projects it is worth considering whether a lightweight framework fits better.

CustomCGI publishes reference information on CGI programming and server-side web scripting for educational and informational purposes. Code examples are provided as-is for learning; always audit and test scripts in a staging environment before deploying to production. Security vulnerabilities in CGI scripts are a real risk; follow current best practices and review the security guide before deploying any user-facing code.