gTTS: ValueError: Unable to find token seed! Did https://translate.google.com change?

After I send 10-15 requests, I get the following error:

Traceback (most recent call last):
  File "text_to_speech.py", line 25, in <module>
    text_to_speech(data)
  File "text_to_speech.py", line 17, in text_to_speech
    tts.save(f'audio/{key}/def-{i + 1}.mp3')
  File "/home/shoaib/anaconda3/lib/python3.7/site-packages/gtts/tts.py", line 111, in save
    self.write_to_fp(f)
  File "/home/shoaib/anaconda3/lib/python3.7/site-packages/gtts/tts.py", line 124, in write_to_fp
    'tk' : self.token.calculate_token(part)}
  File "/home/shoaib/anaconda3/lib/python3.7/site-packages/gtts_token/gtts_token.py", line 28, in calculate_token
    seed = self._get_token_key()
  File "/home/shoaib/anaconda3/lib/python3.7/site-packages/gtts_token/gtts_token.py", line 59, in _get_token_key
    "Unable to find token seed! Did https://translate.google.com change?"
ValueError: Unable to find token seed! Did https://translate.google.com change?

I thought this might be a bug in the latest release, i.e., 2.1.1 so I tried 1.2.0 and I still get the same error.

I also thought it could be that my IP address is being blocked. I read up on the Quotas & limits and I don’t think that should be an issue as well.

  • Characters per request: 67 (on average), never more than the allowed 5000
  • Requests per minute: never exceeds 15 since I get the error, allowed 300

System information:

  • Operating System: Manjaro Linux
  • Kernel: Linux 5.8.11-1-MANJARO
  • Architecture: x86-64

Thank you for your timely help. ☺️ ✨

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 6
  • Comments: 58 (14 by maintainers)

Most upvoted comments

Yes, that pull request has now been merged, so the url is https://github.com/Boudewijn26/gTTS-token/blob/master/docs/november-2020-translate-changes.md#ladies-and-gentlemen-weve-got-him. What’s perhaps more interesting is what’s going on in https://github.com/Boudewijn26/gTTS. Apart from the lookup of locales, I’ve pretty much gotten it working. I think you can expect a pull request by tomorrow. All in all this wasn’t as bad as I was expecting, so I’m pretty relieved.

To add to this discussion: I, as maintainer of gTTS-token, also intent to look into this further in order to, if possible, ensure compatibility with the new changes Google is rolling out. This has been complicated by the simple fact I haven’t received the new Google Translate yet. It’s not at all uncommon for larger corporations to roll out changes gradually and that indeed appears to be happening here. We don’t have any insight into which regions get this new “feature” first, so we’ll just have to wait for now.

That being said, this is an undocumented API, so we really can’t blame Google for changing this without notice. For what I gather Google has turned a blind eye towards this whole thing. It wouldn’t be too difficult for them to obfuscate the API to such an amount it’d be tremendously difficult to reverse engineer, which is something they haven’t done (yet?) in the many years these projects exist.

As stated, should this problem persist, everyone is free to comment on https://github.com/Boudewijn26/gTTS-token/issues/20 or raise a new issue there (or continue the discussion here, I suppose).

Prompted by https://github.com/home-assistant/core/issues/42911#issuecomment-724712969, I’ve decided to further my investigation. You can follow along https://github.com/Boudewijn26/gTTS-token/pull/23, coincidentally the CI for that PR hit the same issue. Initial findings do point to big changes being needed to maintain compatibility. I’ll update the PR regularly, so everyone can follow along.

gTTS has been updated to 2.1.2!

It updates gTTS-token to 1.1.4 and a few other various fixes, see changelog.

I’ve also reworked the GitHub Action workflows and “marked” with PyTest the tests that try to access the /translate_tts URL (most of them) and allowed them to fail for now. Like I stated above, I will try to look into a better way to work around this.

I started getting this last week periodically. It happened about 10 times to me today. I have no clue.

Just closing this, as it was kept for discussion after the issue was fixed and then bit of an HA direction talk but it’s starting to derail a bit.

So cool to see this go to HA, thanks for your work all. I’ll sure try to contribute when I can!

Seems like the old solution in HA finally broke completely now… 😦

https://github.com/home-assistant/core/issues/43801

Thank you for your work on this!

Feel free to tag me when the new release is out so I can open the necessary PRs in the upstream repositories (Home Assistant, Mycroft).

I’d create a feature branch - you’d basically have to check it out and run HA from there and then test google_translate.

@hmmbob Could you properly test it if I do it?

Just checked with one of the core devs (Frenck): there is no need for you to redo your package to use aiohttp instead of requests (basically, the answer was “he can use anything he likes” lol) Work will need to be done in integration the package correctly in the HA Google TTS component

Wish I could be of help, but I don’t have the programming experience to build this myself…

aiohttp client is pretty nice and maybe what I should head towards—gTTS has been using requests since 2014! But the work for async requests is all over the place, a lot of it isn’t maintained and/or is for older Python 3.

Hi all, @marvin-w & @Boudewijn26

gTTS 2.2.0 has been published! 🎉 Big changes are #244 & #245

(FYI, gTTS 2.2.1 is out, bug fix)

On languages

Optimize the language retrieval bit since it’s not reliable enough anymore. Perhaps switching back to a more static language list (obtained via the same means, but checked in into the repo).

This is exactly what I did. I figured out a way to programmatically extract it using the new Google Translate (code not yet “GitHub-ready”) and I will add this to the repo, but out of the main code. After that, my idea is to have a GitHub Action run periodically, which could create a PR if it detects a change. A new patch version of gTTS could then be released.

What’s next—

  • I will rework the inclusion of languages under the hood, so it can be automated (I wanted to get this out ASAP)
  • I will rework gTTSError and have a less janky error management
  • I will work strip out all the old <Python 3.6 stuff, and modernize especially adding coroutine (async/await) support

@marvin-w:

Feel free to tag me when the new release is out so I can open the necessary PRs in the upstream repositories (Home Assistant, Mycroft).

Here you go! 😄 As I wrote earlier, I know that HA uses its own version of an old gTTS, I’m wondering if 2.2.0 can be integrated as-is, or if it needs to enhanced (i.e. Python 3, async/await, etc). I would love to see HA use gTTS directly, and I’m really open to do any changes in this regard.

Hi all,

I’ve merged in #244 with @Boudewijn26’s new audio download code (thanks again! 🙏)

Languages

Still working on the languages, which I’m making good progress on. I’ve identified where the language codes that provide TTS are (vs. all language codes—not all languages in Google Translate provide text-to-speech), I just need to fetch them, with some RegEx magic. Still aiming to push gTTS 2.2.0 Nov 14 (GMT-5).

That’s ok. Maybe we should switch to your issue at HA for this effort?

@hmmbob Ah yeah that was imminent. Sadly did not have any time to work on the above to make gTTS more HA-friendly. 😭

@pndurette Your lib uses the requests package. I think one reason for them to not go with it might be the fact that you aren’t using the aiohttp package instead. Also, one should probably be able to inject the websession directly into the library.

I’m not quite sure on how I’d tackle the update on HA side, I’ll give them a ping in their discord and let them decide. I hope someone of them will reply here 😃.

Thank you @pndurette, you’re too kind. I was wondering the same thing about jQ1olc, perhaps it could be a future task for gTTS-token to determine the name of the RPC.

On the language retrieval: I haven’t had a look at the changes there, so it might perhaps be something we can do reliably. I do see a good case for checking them into the repo to prevent flakiness.

Yeah, this is starting to get tough to maintain/counter. It’s a pretty unorthodox usage of this translate endpoint after all…

But will pull in the updated gtts-token and other fixes and do a release later today.

The underlyting gtts-token library was just updated with this change: https://github.com/Boudewijn26/gTTS-token/commit/8d681855214b093c78d5a5da4fa19f92c4e233ef and it was released already.

However, this still doesn’t fix the actual problem but instead just hides it in the background. (Retry 5 times or throw error)

I found the post,

Add the qualifier ‘&client=tw-ob’ to the end of your query. https://translate.google.com/translate_tts?ie=UTF-8&q=test&tl=zh-TW&client=tw-ob

This answer no longer works consistently. Your ip address will be blocked by google temporarily if you abuse this too much.

Seems like adding client=tw-ob doesn’t work consistently though.

found a guy saying to add client=tw-ob in the url ( can´t be sure why, and if it works 100% of the time)

https://translate.google.com/translate_tts?ie=UTF-8&q=Annoying%20bug&tl=en-US&client=tw-ob

EDIT: BTW, you can use this url to download, so you don´t even need this repo

@afonsosantos I am using Python 3.8.5, I doubt it could be an issue related to Python.

@thedaynos You are right, the error isn’t that often. For me, the max number of continuous failed attempts were 3 and it is occurring on the line tts.save function call.

That’s interesting. Mine was breaking on the tts.save line, so this wasn’t working for me. This is how I got it working…

import os
from gtts import gTTS
count=1
text = 'Your sentence requiring text to speech'
file_path = 'text.mp3'
tts = gTTS(text=text, lang='en', slow=False)
while True:
	try:
		tts.save(file_path)
                break
	except: 
		print('got the issue '+str(count))
                count+=1

I have the count in there just out of curiosity, obviously you don’t need that. I just tried this for about 20 minutes and got the error maybe 20% of the time. Only once did the count get to 2.

Seems to be working without crashing now.