Downloading captions always returns a 403 - youtube-api

When I call the captions.download endpoint with an ID that we retrieve from the captions.list endpoint, it always returns a 403. For example:
https://www.youtube.com/watch?v=1HRwpwOj4aA
I call captions.list with:
GET https://www.googleapis.com/youtube/v3/captions?part=id&videoId=1HRwpwOj4aA&key={YOUR_API_KEY}
This is response:
cache-control: private, max-age=0, must-revalidate, no-transform
content-encoding: gzip
content-length: 236
content-type: application/json; charset=UTF-8
date: Sat, 23 May 2015 17:55:57 GMT
etag: "dhbhlDw5j8dK10GxeV_UG6RSReM/Rztb3ln4Zb6O07vb7_KSZi2y1NM"
expires: Sat, 23 May 2015 17:55:57 GMT
server: GSE
vary: Origin, X-Origin
{
"kind": "youtube#captionListResponse",
"etag": "\"dhbhlDw5j8dK10GxeV_UG6RSReM/Rztb3ln4Zb6O07vb7_KSZi2y1NM\"",
"items": [
{
"kind": "youtube#caption",
"etag": "\"dhbhlDw5j8dK10GxeV_UG6RSReM/pwH-4wtyQJz0U3l57fA8uKm4e1I\"",
"id": "kHlUsiuNS4TjB25loauZNXGrjK91I1tEdNyOpTRNA78="
}
]
}
When I use the above id to call captions.download:
GET https://www.googleapis.com/youtube/v3/captions/kHlUsiuNS4TjB25loauZNXGrjK91I1tEdNyOpTRNA78%3D?key={YOUR_API_KEY}
This is response:
403 Forbidden
cache-control: private, max-age=0
content-encoding: gzip
content-length: 29
content-type: text/html; charset=UTF-8
date: Sat, 23 May 2015 17:59:05 GMT
expires: Sat, 23 May 2015 17:59:05 GMT
server: GSE
vary: Origin, X-Origin
Forbidden
Any ideas what could be happening here?

From the YouTube API docs:
403 Forbidden: The permissions associated with the request are not
sufficient to download the caption track. The request might not be
properly authorized, or the video order might not have enabled
third-party contributions for this caption.

Instead caption download API that sometimes returns 403 (if video not have enabled third-party contributions for this caption) you can use youtube.com/api/timedtext

what you wrote above about "only works for videos your google account owns" is not my experience. I just successfully ran captions.download on a video (about dog training) which I definitely do not own - do not even have a dog. However, I have tested the exact same code on the video mentioned here on stackoverflow and get a 403 error.
So no it doesn't always return a 403 sometimes it returns a 200! Try it with the dog video mentioned above:
python captions.py --videoid="jBN2_YuTclU" --action="download" --captionid='8S2GjnNfitU5HHoLyTeLxq_W1dP29YRFC8E8vFBUtws='
with the code you probably already have here.
It will need your client_secrets.json downloaded from the Google credentials page somewhere and a missing file youtube-v3-api-captions.json which you can get from here. The code launches a browser where you log in for OAuth2 authorisation.
Still, there must be a reason why it works for some videos and not others. #Abhishek might have it above. The wrong comment has been upvoted there. Nothing in the output of captions.list for a video that allows captions downloads and a video that does not is obviously different which would explains why one works and the other does not. If anyone can supply which {'key':'value'} pair in the youtube api controls this would be helpful.

Status 403 Forbidden means that nobody has the right to access that URL. You shouldn't receive that message if you have the wrong API key, for example; that should give Status 401 Unauthorised. I'd check the URL carefully.

Related

Error 500 Adding Thumbnails with Youtube API v3

I have an ID of a Youtube video and like to add a Thumbnail with the google-api-client (Ruby). My request looks like this
result = client.execute(:api_method => youtube.thumbnails.set, :parameters => { :videoId => my_video_id, :media_body => file })
What result.data returns is this
<Google::APIClient::Schema::Youtube::V3::ThumbnailSetResponse:0x86435518 DATA:{"error"=>{"code"=>500, "message"=>nil}}>
I can't figure out, what the problem is here. I tried to use a path to a file on my local machine as well as a URL. Even an empty String as the file location or leaving out the media_body leads to the 500 error.
Does anyone of you know, what's going on here and why I don't get a clear error response?
Edit: It seems to be not the fault of the google-api-client, because testing the same request in the Google APIs Explorer produces the same result:
Response
500 Internal Server Error
cache-control: private, max-age=0
content-encoding: gzip
content-length: 66
content-type: application/json; charset=UTF-8
date: Wed, 19 Feb 2014 14:24:23 GMT
expires: Wed, 19 Feb 2014 14:24:23 GMT
server: GSE
{
"error": {
"code": 500,
"message": null
}
}
Not all channels are enabled for custom thumbnails; I suspect that if you're getting an error, it might be because you're attempting to set a custom thumbnail for a video in a channel that isn't enabled. There's more info at https://support.google.com/youtube/answer/72431?hl=en
Could you follow the steps in that help article and see whether you have an option in the web UI to set a custom thumbnail? If you don't, then your channel isn't enabled.
Getting back a HTTP 500 response is obviously unhelpful, though, and makes it difficult to confirm that that's what's going on. We can follow up with the engineering team about that to get a helpful error returned once we confirm whether your channel is enabled or not.

httpclient with twitter gives me unauthorized 401 strict-transport-security: max-age=631138519

When using httpClient to connect to twitter I Always get this response
responseString{StatusCode: 401, ReasonPhrase: 'Unauthorized', Version:
1.1, Content:System.Net.Http.StreamContent, Headers: { strict-transport-security: max-age=631138519 Date: Fri, 31 Jan 2014
00:35:10 UTC Set-Cookie: guest_id=v1%3A139112851013762159;
Domain=.twitter.com; Path=/; Expires=Sun, 31-Jan-2016 00:35:10 UTC
Server: tfe Content-Length: 63 Content-Type: application/json;
charset=utf-8 } }
System.Net.Http.HttpResponseMessage
I googled
strict-transport-security: max-age
found people suggested to change the access setting of the twitter app to Read, Write and Access direct messages, i Did so but nothing changed , so if any one faced the same problem or any body has suggestions , it would be appreciated
There are multiple reasons this might happen. I have this question on the LINQ to Twitter FAQ with several suggestions on how to debug:
https://linqtotwitter.codeplex.com/wikipage?title=LINQ%20to%20Twitter%20FAQ

AFNetworking set image without extension

There is a method in AFNetworking that can set image conveniently:
- (void)setImageWithURL:(NSURL *)url
placeholderImage:(UIImage *)placeholderImage
but if the url image have no extension(like http://static.qyer.com/album/user/330/21/QkpVQBsHaA/670), there are some problems,sometimes the image can be displayed exactly some times it is not displayed.
I found a method
[AFImageRequestOperation addAcceptableContentTypes:<#(NSSet *)contentTypes#>];
how should I set the contentTypes?
If you curl the URL provided, you can see the problem:
curl -i -X HEAD http://static.qyer.com/album/user/330/21/QkpVQBsHaA/670
HTTP/1.0 200 OK
Server: nginx/1.0.11
Date: Fri, 29 Mar 2013 02:03:24 GMT
Content-Type: application/octer-stream
Last-Modified: Tue, 19 Mar 2013 09:40:23 GMT
ETag: "53430075-9814c-4d843e4fc6fc0"
Accept-Ranges: bytes
Content-Length: 622924
Powered-By-ChinaCache: MISS from 060531Q354
Powered-By-ChinaCache: MISS from 060532235y
Connection: close
Content-Type: application/octer-stream (which is, strangely, a misspelling of application/octet-stream), is not a valid image mime type. If you have any control over the server, I would strongly recommend you fix this to send real mime types—for the sake of everyone accessing the CDN.
Otherwise, I would recommend you add */* to the list of acceptable content types. This should accept anything thrown at it. You can also manually specify any content types you might expect the CDN to serve, including application/octer-stream.

Facebook 'like' - redirect path to the wrong URL

I'm trying to get the Facebook 'like' button working on a site that has some job listings for different companies - each company can have various incoming links (such as http://apply.co/xentrix_studios or http://apply.co/xentrix_studios/facebook that are redirected to a general list of that company's jobs at http://apply.co/jobs.
Here's the Facebook debug for one of the links: https://developers.facebook.com/tools/debug/og/object?q=apply.co%2Fxentrix_studios
Look at the redirect path. Facebook is going from /xentrix_studios to /jobs to the root at http://apply.co. So, the readings it's giving us are for the root url, which is obviously not what we want.
How can I get Facebook to just stay at the right page after it follows the incoming link?
Your server is returning a 301 redirect for that URL. If you want Facebook to treat a URL as being a real URL, it needs to return content including the meta tags that tell Facebook what image/description/etc to use.
I checked this with
curl -A "facebookexternalhit/1.1" -i "http://apply.co/xentrix_studios"
The response was
HTTP/1.1 302 Moved Temporarily
Server: nginx/0.7.67
Date: Wed, 23 Nov 2011 10:10:55 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Location: http://apply.co/jobs
Cache-Control: no-cache
X-Ua-Compatible: IE=Edge,chrome=1
Set-Cookie: _rubyjobs_session=BAh7DUkiD3Nlc3Npb25faWQGOgZFRiIlZjk3NDk0YTI0ZGIxMDNhODA2YWE0YTgxOGUyNmZkNTNJIg5qb2JfcmVhZHMGOwBGWwBJIg5qb2Jfc2F2ZXMGOwBGWwBJIhB2aXNpdF9jb3VudAY7AEZbAEkiCXBhdGgGOwBGSSIUeGVudHJpeF9zdHVkaW9zBjsAVEkiDGxpbmtfaWQGOwBGaQBJIghhbGkGOwBGaQKbAUkiCHRsaQY7AEZpAnUE--996d80cb1a2b170c46b6e8f09dcef447fb882917; path=/; HttpOnly
X-Runtime: 0.036089
Content-Length: 86
X-Varnish: 1415265483
Age: 0
Via: 1.1 varnish
<html><body>You are being redirected.</body></html>

Google OAuthGetRequestToken returns "signature_invalid"

Trying for hours to get a request token using Google OAuthGetRequestToken but it always returns "signature_invalid".
For a test I use the oAuth Playground to successfully request the token. Here are the results:
Signature base string
GET&https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthGetRequestToken&oauth_callback%3Dhttp%253A%252F%252Fgooglecodesamples.com%252Foauth_playground%252Findex.php%26oauth_consumer_key%3Dwww.embeddedanalytics.com%26oauth_nonce%3D56aa884162ed21815a0406725c79cf79%26oauth_signature_method%3DRSA-SHA1%26oauth_timestamp%3D1321417095%26oauth_version%3D1.0%26scope%3Dhttps%253A%252F%252Fwww.google.com%252Fanalytics%252Ffeeds%252F
Request/Response
GET /accounts/OAuthGetRequestToken?scope=https%3A%2F%2Fwww.google.com%2Fanalytics%2Ffeeds%2F HTTP/1.1
Host: www.google.com
Accept: */*
Authorization: OAuth oauth_version="1.0", oauth_nonce="56aa884162ed21815a0406725c79cf79", oauth_timestamp="1321417095", oauth_consumer_key="www.embeddedanalytics.com", oauth_callback="http%3A%2F%2Fgooglecodesamples.com%2Foauth_playground%2Findex.php", oauth_signature_method="RSA-SHA1", oauth_signature="qRtorIaSFaQdOXW1u6eMQlY9LT2j7ThG5kgkcD6rDcW4MIvzluslFgYRNTuRvnaruraNpItjojtgsrK9deYRKoHBGOlU27SsWy6jECxKczcSECl3cVAcjk7dvbywFMDkgi1ZhTZ5Q%2BFoD60HoVQUYnGUbOO0jPXI48LfkiA5ZN4%3D"
HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Date: Wed, 16 Nov 2011 04:18:15 GMT
Expires: Wed, 16 Nov 2011 04:18:15 GMT
Cache-Control: private, max-age=0
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Content-Length: 118
Server: GSE
oauth_token=4%2FmO86qZzixayI2NoUc-hewC--D53R&oauth_token_secret=r0PReF9D83w1d6uP0nyQQm9c&oauth_callback_confirmed=true
I am using Fiddler to trace my calls. It returns the Signature base string:
GET&https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthGetRequestToken&oauth_callback%3Dhttp%253A%252F%252Fgooglecodesamples.com%252Foauth_playground%252Findex.php%26oauth_consumer_key%3Dwww.embeddedanalytics.com%26oauth_nonce%3Dl9Jydzjyzt2fJfM3ltY5yrxxYy2uh1U7%26oauth_signature_method%3DRSA-SHA1%26oauth_timestamp%3D1321417107%26oauth_version%3D1.0%26scope%3Dhttps%253A%252F%252Fwww.google.com%252Fanalytics%252Ffeeds%252F
Aside from the oauth_timestamp and oauth_nonce (which should be different), the base string are pretty much identical.
Anyone know what I am doing wrong?
Update 11/20/2011 Thinking it might be something wrong with my RSA-SHA signing, I have since tried HMAC-SHA. It gives the same results. I thought it might be beneficial to include the Fiddler results (I added carriage returns to have it format better).
GET https://www.google.com/accounts/OAuthGetRequestToken?
scope=https%3A%2F%2Fwww.google.com%2Fanalytics%2Ffeeds%2F HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Authorization: OAuth oauth_version="1.0",
oauth_nonce="7C4C900EAACC9C7B62E399A91B81D8DC",
oauth_timestamp="1321845418",
oauth_consumer_key="www.embeddedanalytics.com",
oauth_signature_method="HMAC-SHA1",
oauth_signature="ows%2BbFTNSR8jVZo53rGBB8%2BfwFM%3D"
Host: www.google.com
Accept: */*
Accept-Encoding: identity
Response
HTTP/1.1 400 Bad Request
Content-Type: text/plain; charset=UTF-8
Date: Mon, 21 Nov 2011 03:16:57 GMT
Expires: Mon, 21 Nov 2011 03:16:57 GMT
Cache-Control: private, max-age=0
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Content-Length: 358
Server: GSE
signature_invalid
base_string:GET&https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthGetRequestToken
&oauth_consumer_key%3Dwww.embeddedanalytics.com
%26oauth_nonce%3D7C4C900EAACC9C7B62E399A91B81D8DC
%26oauth_signature_method%3DHMAC-SHA1
%26oauth_timestamp%3D1321845418
%26oauth_version%3D1.0
%26scope%3Dhttps%253A%252F%252Fwww.google.com%252Fanalytics%252Ffeeds%252F
Update 11/24/2011 - I want to add more information based on the answers from #Meysam and #Bob Aman. First, my domain is properly registered with Google. I have been using AuthSub for quite some time now with Target URL path prefix set to http://www.embeddedanalytics.com/authsubsuccess.html. Now when I go to the Manage Domains section it states my oAuth consumer key is www.embeddedanalytics.com. Now perhaps this could be a problem. In the Registration for Web-Based Applications document it states:
If you're using the OAuth interface, this URL (the "Target URL path prefix") must match the value of the oauth_consumer_key parameter
In my case I have a target URL different from my oauth_consumer_key. Could this be a problem? I use www.embeddedanalytics.com as the consumer_key in the playground and it works. I don't want to mess with the target URL because it is currently being used with my AuthSub authorizations.
I assume you have not registered your application domain with Google. Therefore, whatever consumer secret you are using to sign your request (in HMAC-SHA1 method) will be denied unless you provide anonymous as your oauth_consumer_key and consumer secret. This way, Google will recognize you as an unregistered application and will successfully return you a Request Token.
If you use the HMAC-SHA1 method, the Consumer Secret and Token Secret will be used to sign your requests. These two secret parameters are known both to your application, and Google, and act like a secret key in a symmetric encryption algorithm.
In order to use RSA-SHA1 method however, you should have already uploaded your Public Key to the server (Google Server) during the registration process of your application. After that, you will use your Private Key to sign your OAuth requests. In your case, since you have not registered your application, Google is not aware of your Public Key, and therefore using RSA-SHA1 method to sign your requests with an unknown Private Key is of no use.
The first method is usually preferred over the RSA-SHA1 method for performance reasons. (symmetric encryption is faster than asymmetric one)
So this is the way I could successfully get a Request Token in the OAuth Playground:
Set 'oauth_consumer_key' to anonymous (unless you have
registered your application and have a real Consumer Key)
Set 'consumer secret' to anonymous (unless you have registered your
application and have a real Consumer Secret)
Choose https://www.google.com/analytics/feeds/ as the scope of request.
Press 'Request token' button
Result:
GET /accounts/OAuthGetRequestToken?scope=https%3A%2F%2Fwww.google.com%2Fanalytics%2Ffeeds%2F HTTP/1.1
Host: www.google.com
Accept: */*
Authorization: OAuth oauth_version="1.0", oauth_nonce="116d4df85e784f51cf40f0bc3a967883", oauth_timestamp="1322083727", oauth_consumer_key="anonymous", oauth_callback="http%3A%2F%2Fwww.googlecodesamples.com%2Foauth_playground%2Findex.php", oauth_signature_method="HMAC-SHA1", oauth_signature="vVxpbtHlTR%2BJ1yT%2BYS1HOvRzhOs%3D"
HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Date: Wed, 23 Nov 2011 21:28:47 GMT
Expires: Wed, 23 Nov 2011 21:28:47 GMT
Cache-Control: private, max-age=0
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Content-Length: 118
Server: GSE
oauth_token=4%2F7E_YtZFHuKFPbuAGuCzyj2AsHcha&oauth_token_secret=NHZBJCj2BPxR2HQZhCTwdq2A&oauth_callback_confirmed=true
Now that you have acquired oauth_token and oauth_token_secret, you can press Authorize button. This will redirect you to the login page of Google (if you are not signed in) and then to the page you grant access to the application. By granting access, you will get back to the callback url in the playground with a verifier code. Pressing 'Access token' button, will get you the access token:
GET /accounts/OAuthGetAccessToken HTTP/1.1
Host: www.google.com
Accept: */*
Authorization: OAuth oauth_version="1.0", oauth_nonce="c222a88cc9f027430b239f4cc6f3f154", oauth_timestamp="1322084080", oauth_consumer_key="anonymous", oauth_verifier="TA6vWcDJC51A9YwMNfmUzmUQ", oauth_token="4%2F7E_YtZFHuKFPbuAGuCzyj2AsHcha", oauth_signature_method="HMAC-SHA1", oauth_signature="q9M%2BjeHNxB2ONPd1DPMn6GriUC8%3D"
HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Date: Wed, 23 Nov 2011 21:34:40 GMT
Expires: Wed, 23 Nov 2011 21:34:40 GMT
Cache-Control: private, max-age=0
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Content-Length: 103
Server: GSE
oauth_token=1%2Fxy49iwSQEcqSDbo3cKO-UuPLqvt9qKFit9vaLqR6P-M&oauth_token_secret=IJWB1CVSQfYJJPrf9jXv6SS8
*Note: One time, I got the signature_invalid response too, even though I had entered anonymous credentials. But after trying again and pressing 'Request token' button one or two more times I made it. I think this should be due to how nonce and timestamp parameters work to sign the request. This could be the cause of problem. Read this article for more info.
Further reading:
Managing the OAuth key and secret
Registration for Web-Based Applications
Googler here. Haven't fielded OAuth 1 questions in a long time because everyone's moving to OAuth 2 (and you should too) but I'll try to go through the usual suspects on invalid signature errors:
Your server's clock may be wrong. There's a timestamp component and it needs to match ours pretty closely. Try updating your clock against one of the major reference time servers. This happens, but it's an uncommon issue.
Depending on how low-level the OAuth client you're using is, you may have forgotten to supply part of the key used to generate the signature. The key has two pieces, colon-separated, IIRC. In some parts of the protocol, only one half is needed, but for other parts of the protocol, you need both. I've seen cases where someone kept supplying only the first half when both were needed. Actually, I think I made this mistake myself a couple times.
Probably not an issue in your case, because you haven't even gotten past the request token, but OAuth 1 requires you to sign the URI query parameters. Failure to do this will cause the signature base strings to mismatch, thus causing the signature to be invalid.
By far the most common issue is improper encoding. This usually gets expressed as signatures that work sometimes, but fail other times, because sometimes you get lucky and nothing needs to get encoded. I suspect this is what #Meysam ran into based on his comment that he pressed the button a few more times and suddenly it worked.
By the way, if you have to use OAuth 1, you should be using HMAC-SHA1 unless you've got a really good reason to do RSA-SHA1.

Resources