it is because the protocol of terminals (and pseudo-terminal like
xterm). They send just byte of data, either as input (e.g. key pressed), or as output to print (normal text).
But not all can be done with usual ASCII characters (or extended with UTF-8 codes). E.g. if a key has not a common character, it is sent as an escape sequence, usually as:
<esc> '[' (<keycode>) (';'<modifier>) '~'
You find the many of such sequences, e.g. in Wikipedia: https://en.wikipedia.org/wiki/ANSI_escape_code#Terminal_input_sequences
E.g. as vt sequence:
<esc>[5~ - PgUp
So, as expected, the terminal will send a PageUp code. This is fully correct.
So the real problem is: why the terminal will print such codes? There can be various causes: e.g. wrong terminal setting (
TERM), etc. But usually it is just that the receiving program is not able to interpret it, and so it may just echo to the screen. For example, usually
bash can recognize PageUp, but a shell utility (e.g.
cat) not, so whey the foreground process is
cat, you get the echo (so the code), but when bash is foreground (so waiting for input), it will interpret correctly the sequence).
Note: PageUp is usually sent to the program, and not used by the pseudo-terminal (e.g. to scroll), but this may be changed in the settings, and maybe according to the display mode of the foreground program).
Note: some operating systems may use different escape sequences (if I remember correctly, macos terminal uses a different sequence for PageUp), and this may confuse some programs (mainly if the terminal settings are not correct).