In case it would help, I have provided the source of the methods that piece together my output and print it. I use HTTP::Headers to do the headers and my own code to assemble the HTML body. // Darren Duncan sub send_to_user { my $self = shift( @_ ); print STDOUT $self->to_string( @_ ); } sub to_string { my ($self, $endl) = @_; my $ret_value; my $status; defined( $endl ) or $endl = "\015\012"; $self->do_replacements(); my $http = $self->{$KEY_HTTP_HEADER}; if( my $url = $self->{$KEY_REDIRECT_URL} ) { $status = '301 Moved'; # used to be "302 Found" $http->header( status => $status, uri => $url, location => $url, window_target => 'external_link_window', ); $ret_value = $http->as_string( $endl ); } else { $status = '200 OK'; $http->header( status => $status, content_type => 'text/html', ); my $http_header = $http->as_string( $endl ); require HTML::TagMaker; my $html = HTML::TagMaker->new(); my $header = $html->start_html( title => $self->{$KEY_TITLE}, author => $self->{$KEY_AUTHOR}, meta => $self->{$KEY_META}, style => { src => $self->{$KEY_CSS_SRC}, code => $self->{$KEY_CSS_CODE}, }, head => $self->{$KEY_MAIN_HEAD}, body => $self->{$KEY_BODY_ATTR}, ); my $body = join( '', @{$self->{$KEY_MAIN_BODY}} ); my $footer = $html->end_html(); $ret_value = $http_header.$header.$body.$footer; } my $is_mod_perl = ($ENV{'GATEWAY_INTERFACE'} =~ /^CGI-Perl/); if( $is_mod_perl ) { $ret_value = 'HTTP/1.0 '.$status.$endl.$ret_value; } return( $ret_value ); }