You should use the CGI module once you have loaded it. It makes it much simpler to follow the correct rules for an HTTP page.
As has been observed, you need to print an HTTP header before the HTML body, and you can do that with print $cgi->header which defaults to specifying a content type of text/html and a character set of ISO-8859-1, which is adequate for many simple HTML pages. It also generates a <meta> element within the HTML that contains the same information.
This short program shows the idea. I have added a trivial table that shows how you could include that in the page. As you can see, the CGI code is much simpler than the corresponding HTML.
use strict;
use warnings;
use CGI qw/ :standard /;
print header;
print
start_html('My Title'),
p('Hello Perl am HTML'),
table(
Tr([
td([1, 2, 3]),
td([4, 5, 6]),
])
),
end_html
;
output
Content-Type: text/html; charset=ISO-8859-1
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">
<head>
<title>My Title</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>
<body>
<p>Hello Perl am HTML</p><table><tr><td>1</td> <td>2</td> <td>3</td></tr> <tr><td>4</td> <td>5</td> <td>6</td></tr></table>
</body>
</html>