in reply to wrong Content-Length

        $browser->recv($chunk, 10000);

Most common platforms use IO blocks of 4096 bytes in size, so reading *just* that much is usually a good idea, that way you only use one block, which is probably big enough, and no more. If you really like 10000, then you should use 10240 instead, but I know of very few platforms that use IO blocks of that size. Even if you use the smaller block size when reading, odds are you often won't even fill that up entirely since most HTTP requests aren't that big, and if one is, you'll probably start reading before much of it has been sent. But at least this way you only use one block instead of the three with 10000.

last if ($chunk =~ "\r\n\r\n");

Popcorn Dave addressed this. \r\n, though a common idiom, cannot be used to portably match CRLF. \n means linefeed on Unix, carriage return on MacOS, and on Windows, when reading from a text file, CRLF is converted to LF so \n works properly. Instead of \r\n, use the octals \015\012 to match CRLF. Please also read this.

Other then that, everything looks pretty good. You might want to consider replacing length() with something else though, since length() returns the length of a string in characters, whereas Content-Length: contains the size of the POST data/response in bytes, which means multi-byte Unicode characters might cause you some problems. See this node here. Also, Many of those regular expressions could probably be replaced with the more effecient simple string manipulation functions like index(), rindex(), and substr().