Instead, you can try:
(\d*+)(?>[^"]++|"(?!id_str":))+"id_str":"(\d*+)",(?>[^"]++|"(?!location":))+"location":"([^"]*+)"
The idea here is to eliminate backtracks as much as possible using only possessive quantifiers and atomic groups with limited character classes (as in the last capture group)
For example, to avoid the first lazy quantifier, I use this:
(?>[^"]++|"(?!id_str":))+
the regex engine will accept all characters that are not double quotes as much as possible (and do not register a single countdown position because the possessive quantifier is used) when the double quote is found as a control if it is not followed by the id_str": anchor. All this part is wrapped in an atomic group (without going back inside), repeated one or more times.
Do not be afraid, using an appearance inside which you will not succeed quickly and only if a double quote is found. However, you can try the same with i if you are sure that it is less frequent than " (or a rare character earlier if you find):
(?>[^i]++|i(?!d_str":))+id_str":(...
EDIT: the best choice here looks , which is less common: (200 steps versus 422 with double quote)
(\d*+)(?>[^,]++|,(?!"id_str":))+,"id_str":"(\d*+)",(?>[^,]++|,(?!"location":))+,"location":"([^"]*+)"
To have better characteristics, and if you have such an opportunity, try adding an anchor ( ^ ) to your template if this is the beginning of a line or a new line (with multi-line mode).
^(\d*+)(?>[^"]++|"(?!id_str":))+"id_str":"(\d*+)",(?>[^"]++|"(?!location":))+"location":"([^"]*+)"