This is empirically a practical attack: attackers successfully executed a common password brute force attack against GitHub in late 2013 by using a botnet with 40,000 distinct remote addresses:
Before that, attackers would just wait for new usernames to appear on the scoreboard/chat and check them against password dumps. The easy come, easy go nature of bitcoin made it particularly lucrative.
Password reuse is a massive issue. At a glance, one might wonder why most sites need to care so much since they don't deal with money. Who cares about a forum like HN? But consider that it's easier to audit/impede new accounts with anti-spam measures, so there's value in taking over old accounts. And you don't want people with moderation tools getting attacked either. Ideally, it's nice to be able to trust an account with 1,000 posts more than one with 0 posts, but that evaporates when accounts are easily stolen.
Aside, how do you implement account-locking without making it trivial for users to DoS each other that way?
By adding an (increasing) time delay after each failed attempt. However many sites, banking in particular, just lock your account and you have to call them on the phone to reopen it. Totally open for massive DoS but the world still stands.
Notice that banking websites can get away with it, yet surely you weren't only talking about banking when you said "online attacks".
Because it's trivial to implement decent ratelimiter which stops attackers, but still allows normal users to login.
It's also not a trivial issue. It's cheaper and cheaper to attack a website with unlimited IP addresses. Which dimension are you going to rate-limit?
There is no lock that cannot be lockpicked. The only difference between a good lock and a bad lock is amount of time it takes to lockpick it.
And captcha only makes brute-force somewhat more expensive. You likely have to use a 3rd party captcha service (like Recaptcha) which incurs network volume amplification since you need a req/res to Google just to render GET /login. It also shows how hard of a problem captcha is that you can't just roll it yourself.
You're still not addressing the problem since IP addresses are so cheap. I only need 1,000 IP addresses to try the top 1,000 passwords in parallel no matter what your rate-limit scheme is unless you plan on letting me lock the authentic user out of their own account.
You've wandered from your original claim that bruteforce doesn't even happen these days, and I'm certainly not saying we are helpless against it. In the end, I'd simply suggest that this problem is harder than you originally gave it credit for, and maybe that's something we can agree on.
You want simple concrete example of how to stop all that "unlimited amount of ip addresses with captcha solver service" stuff? No more than 20 attempts per day with ip different from the ip of the last successful login. Here it is, you just solved the "bruteforce problem". That's all you have to do. Other things are just quality of life improvements.
But if care about security, you might as well solve the problem properly instead of wasting your time implementing "your password must have a capital letter and a number" snake-oil features which only annoy your users.
For online attacks, an attacker can't even try the top 1000 passwords on for an account in any major website in reasonable time without triggering the alarm, as they all(?) have rate limiting (usually in the form of account lockdown after single-digit failed attempts).
For offline attacks, there first needs to be a breach. While they undoubtedly happen, they are very infrequent events. But once they happen, you should assume all passwords would be cracked very fast. Hackers can get their hands on a lot of computing power, and the brute-forcing attempts are not alphabetical, but rather clever how-humans-chose-passwords models. You're relatively safe because of the low frequency of breaches, not because a hacker trying trillions of passwords a second will be frustrated by your password choosing policy. I'm sure most of the passwords from the breaches would be attempted anyway.
Credential stuffing[0] is the real issue. If there was an API to test that a user isn't using this password on other websites, that would be very useful.
[0] https://www.owasp.org/index.php/Credential_stuffing