Some parts of that example seem pretty silly. URLs for example: he describes how just about anything can be passed in as a URL, and requests attempts to call __str__ or __unicode__ on it and then parse it. Considering (essentially?) all types in Python have __str__, this is a perfectly reasonable place to use the Any type. The issue isn't with the expressiveness of the typing system, but with the absurd flexibility of input handling by requests.
‘object’ is the base class of all types: you can put anything into an ‘object’, and you can only do very generic operations like str() on what you get out of an ‘object’ without further checks like isinstance().
‘Any’ is an unsound escape hatch that disables type checking: you can put anything into an ‘Any’, and you can do anything with what you get out of an ‘Any’, and the type checker will make no effort to stop you from doing something wrong.
Actually the proper way to handle is to use protocols. They provide already SupportsBytes type, and you can similarly create custom SupportsStr, but IMO it is silly to do that. This approach increases chance of bugs, and it's just easy to use str type and for developer to wrap such value in str(). I believe that's why SupportsStr was not introduced.