Why does getheaders P2P API return more than getblocks? I've been reading through the Bitcoin P2P protocol documentation as well as experimenting with Bitcore library but confused about one thing.

So getblocks seems to return inventory objects, which are just pointers, so you have to make another getdata request using those inventories to get the actual block.

And getheaders seems to return headers from starts to stop. 

They act similar, except that getheaders returns more than just the pointers. I'm confused here because I feel like getheaders should be the "light mode" which only downloads small amount of data compared to getblocks. This is also shown by the fact that getheaders download up to 2000 headers by default while getblocks downloads up to only 500 inventories.

So am i misunderstanding any of this? Why does getheaders return more information than getblocks AND also return more results that getblocks (2000 vs 500)?
Really getblocks should have been called getblockhashes , as the response contains just block hashes, not full blocks.

Every block can be observed in three different ways:


The full block, containing all transactions and header information.
The block without the transactions, but just the 80-byte header which includes a Merkle root committing to the transactions.
Just the 32-byte hash of the block header (which is used to identify the whole block, and is thus also called the block hash).


getblocks was designed to be used for synchronizing blocks. The usual sequence was that node A would send a getblocks, B would respond with an inv with block hashes, A would reply with a getdata for each block he's missing, and B would send over the full blocks using block messages. The limit was 500, as downloading more than 500 blocks at once was presumably deemed too much and pointless (as that could be up to 500 MB of data).

getheaders on the other hand was designed for headers synchronization, something at the time only used by lightweight clients. These would not download (all) full blocks, and the headers sent in response would generally be the only futher communication. As headers are only 80 bytes per block, even 2000 of them is just 160 kB of data.

Since the introduction of headers-first synchronization (which essentially uses getheaders to learn about block hashes and headers simultaneously, and then download missing blocks from multiple peers at once), the old getblocks based synchronization is superseded (it's still implemented for compatibility with software that doesn't have headers-based sync, but other than that inferior in every way except implementation complexity).