Variables declared with let and const have block scope. The way scoping works in Javascript is, a variable can be seen only inside the same block that it's declared, or inside child blocks. Since counter is declared inside the if block, it isn't visible outside. In contrast, since started is declared at the top level, everything in the script can see it.
For what you want, declare counter to be a persistent outside variable:
let started = false;
let counter;
$(document).on("keypress", function(){
    if (!started){
        counter = 0;
        started = true;
    }
    console.log(counter++);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
 
 
But it would make more sense to use just a counter variable, I think, which gets initialized to 0 immediately:
let counter = 0;
$(document).on("keypress", function(){
    console.log(counter++);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
 
 
That's using your original console.log(counter++);, but if you want the value logged to be the current value of counter, use pre-increment instead:
let counter = 0;
$(document).on("keypress", function(){
    console.log(++counter);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
 
 
There's also no need for a huge library like jQuery for something this trivial:
let counter = 0;
document.addEventListener('keypress', () => {
    console.log(++counter);
});