It's actually possible to use the fact that block-times are locally roughly linearly separated to optimize well beyond a binary search. This code typically requires 5 or fewer fetches to find the nearest block to a given unix timestamp, and benchmarks ~10x faster than a binary search: ```python import arrow T = lambda i_block: web3.eth.getBlock(i_block).timestamp ilatest = web3.eth.get_block('latest')['number'] def iblock_near(tunix_s, ipre=1, ipost=ilatest): ipre = max(1, ipre) ipost = min(ilatest, ipost) if ipre == ipost: print('Got it') return ipre t0, t1 = T(ipre), T(ipost) av_block_time = (t1 - t0) / (ipost-ipre) # if block-times were evenly-spaced, get expected block number k = (tunix_s - t0) / (t1-t0) iexpected = int(ipre + k * (ipost - ipre)) # get the ACTUAL time for that block texpected = T(iexpected) # use the discrepancy to improve our guess est_nblocks_from_expected_to_target = int((tunix_s - texpected) / av_block_time) iexpected_adj = iexpected + est_nblocks_from_expected_to_target print() print(f'target timestamp ({tunix_s}) lies {k:.3f} of the way from block# {ipre} (t={t0}) to block# {ipost} (t={t1})') print(f'Expected block# assuming linearity: {iexpected} (t={texpected})') print('Expected nblocks required to reach target (again assuming linearity):', est_nblocks_from_expected_to_target) print('New guess at block #:', iexpected_adj) r = abs(est_nblocks_from_expected_to_target) return iblock_near(tunix_s, iexpected_adj - r, iexpected_adj + r) ``` Test: ```python import arrow tunix_s = arrow.get('2021-03-11T12:34:56').timestamp() block = iblock_near(tunix_s) ``` Output: [![enter image description here][1]][1] [1]: https://i.sstatic.net/elNbu.png