use Devel::Peek qw( Dump ); my $s = chr(0xE9); say length($s); # 1 say $s eq "\xE9" ?1:0; # 1 say utf8::is_utf8($s) ?1:0; # 0 Dump($s); # PV contains E9 utf8::upgrade($s); say length($s); # 1 The string hasn't changed say $s eq "\xE9" ?1:0; # 1 say utf8::is_utf8($s) ?1:0; # 1 But it's now stored differently. Dump($s); # PV contains C3 A9 utf8::downgrade($s); say length($s); # 1 say $s eq "\xE9" ?1:0; # 1 say utf8::is_utf8($s) ?1:0; # 0 Dump($s); # PV contains E9