I am making a call to the google indexing API for job postings:
private $client;
private $httpClient;
public function initClient($kernel)
{
$this->client = new Google_Client();
$this->client->setAuthConfig(JSON_KEY_HERE);
$this->client->addScope('https://www.googleapis.com/auth/indexing');
$this->httpClient = $this->client->authorize();
}
public function sendJob()
{
$endpoint = 'https://indexing.googleapis.com/v3/urlNotifications:publish';
$content = "{
"url": "URL_HERE",
"type": "URL_UPDATED"
}";
$response = $this->httpClient->post($endpoint, array('body' => $content));
}
When making the call to the API, the response given is ‘403 — Forbidden’
.
Any ideas what this error actually means? I have created the service account correctly but cannot replicate success from my dev enviroment.
tehhowch
9,4974 gold badges23 silver badges42 bronze badges
asked Jul 19, 2018 at 15:52
4
After couple days of headache, here is the answer. Open your Google search console.
Prerequisite: You must already have a google service account
click the tri dot button, and click manage property owners:

add google service account email as new owners:

![]()
U13-Forward
67.7k14 gold badges83 silver badges105 bronze badges
answered Feb 12, 2020 at 9:05
![]()
kopikopi
1492 silver badges4 bronze badges
«Make sure that you have added the service account as an Owner in Google Search Console»
Yep. Use the following code snippet to examine the body response for a more detailed error msg.
var body = result.Content.ReadAsStringAsync().Result;
if the error msg looks like the following, then this is the same problem.
«message»: «Permission denied. Failed to verify the URL ownership.»
Worth noting: The new version of the search console is lacking. At the bottom of the left-hand menu is a «go to the old version» link. Click this and then select «verification details» from the gear menu (upper right). Next, click on the link that says «verification details» (seriously!). Here, you will finally see a list of verified owners at the bottom of the page. You can add a new owner here, using the email address of your service account (addr can also be found in your json key file).
answered Nov 8, 2018 at 1:51
JM.JM.
66812 silver badges23 bronze badges
5
Adding to @Glennstar’s comment and @JMs reply there is no longer the old version link (perhaps I never had the old version) but if you click the 3 vertical dots to the right of user owner ‘(you)’ and select ‘manage property owners’ then on the next page click each of the ‘verification details’ links to the right of your domain variations (example.com, http://www.example.com, https://www.example.com etc or whatever you have) and add the owner ie paste in the gserviceaccount.com email address from the json it will then say ownership delegated by current owner to that email address as well.
Once status of that email address had changed from ‘full’ permission to ‘owner’ back on the search console page I could then run the call fine and the original 403 error about being unable to verify URL ownership was gone. Thanks guys, would have been clueless without this.
answered Apr 23, 2019 at 9:09
edindubaiedindubai
1511 silver badge8 bronze badges
Make sure that you have added the service account as an Owner in Google Search Console as described here: https://developers.google.com/search/apis/indexing-api/v3/prereqs#verify-site.
My problem was that we had multiple entries for the domain in the Search Console (with and without www and with and without https); after adding the service account as an owner to all 4 entries it’s working.
answered Aug 2, 2018 at 15:26
MarcGuayMarcGuay
7098 silver badges14 bronze badges
I struggled with this today the whole day… the solution was that i forgot to activate the indexer api in the google cloud console.
answered May 16, 2022 at 18:07
HackRebHackReb
1091 silver badge4 bronze badges
Долгое время головной болью вебмастеров было уведомление Google о том, что какие-то странички на их сайте появились или исчезли. Теперь тихо и без особых фанфар появилась такая фича, как Google Indexing API. Сам Google сообщает
Цитата:
На данный момент Google Indexing API может сканировать страницы с структурированными данными JobPosting или BroadcastEvent, которые встроены в VideoObject
Фактически же это хорошая замена канувшим уже в лету и плохо работающим пингерам, которые я все равно еще не отключал… Приходит бот и ладно…

Но, вернемся к Google Indexing API.
Во-первых, подчеркну, что работает API для всех страниц. По крайней мере, у меня никаких JobPosting нет, только Article, но странички заходят влет.
Во-вторых, не ожидайте напихать в индекс мусор. Бот придет, страничку подберет, а потом может и выкинуть. Все правила, распространяющиеся на запрос индексации в консоли, распространяются и на API.
Вот основная справка:
Да, от sitemap отказываться все равно не рекомендую. Не путайтесь, что вам там рассказывают по ссылке выше.
Необходимо создать проект и сервисную учетку. Она будет конских размеров и к вашему емейлу отношения иметь не будет. Да, на учетках GSuite все тоже замечательно работает. В смысле, что авторизоваться для настройки всего этого счастья можно и из под GSuite-учетки. Я когда упирался, собирался уже найти свою старую гугловую учетку, вот это делать не надо.
Создадите учетку, главное, что нужно сделать — получить JSON-файлик этой самой учетки и, 100 раз подчеркиваю, учетку добавить в Search Console, как владельца(!) не полную, а именно владельца. Иначе Google Indexing API будет выдавать вам ошибку 403, доводя до отчаяния и матов, как меня.
Все описания, которые сейчас есть в интернете, описывают, как добавить владельца в старой версии консоли. Я решил этот квест за вас. Заходите в , но не спешите жмакать в «Добавить пользователя». У вас есть владелец уже в списке, вот тыкайте в три точки справа от надписи «Владелец»

это как раз то, что вам нужно. Вот в том разделе и добавьте делегированного владельца, ту сервисную учетку, которую вы завели раньше.
Дальше все достаточно просто, кидаете себе на хост где-то файлик (я использую PHP, соответственно, файлик брал на этом языке)
Код:
require_once 'google-api-php-client/vendor/autoload.php';
$client = new Google_Client();
// service_account_file.json is the private key that you created for your service account.
$client->setAuthConfig('service_account_file.json');
$client->addScope('https://www.googleapis.com/auth/indexing');
// Get a Guzzle HTTP Client
$httpClient = $client->authorize();
$endpoint = 'https://indexing.googleapis.com/v3/urlNotifications:publish';
// Define contents here. The structure of the content is described in the next step.
$content = '{
"url": "https://olegon.ru",
"type": "URL_UPDATED"
}';
$response = $httpClient->post($endpoint, [ 'body' => $content ]);
$status_code = $response->getStatusCode();
Кто бы что ни придумывал, на HTTPS ресурсы работают замечательно. В setAuthConfig укажете путь к файлику, который вы получили раньше, при заведении сервисной учетки. Все, больше ничего не надо. Можете $status_code себе выводить на первое время. Никакие приседания и дополнительные авторизации не требуются, в т.ч. через Oauth2, как я сначала искал. В $status_code должно быть 200, если заявка на индексирование принята.
Некоторый геморрой я получил при попытке зацепить библиотечку на которой вышеуказанный пример работает. Дело в том, что на данный момент релизнулась версия 2.6, однако, к моему удивлению, ни git clone, ни прямое скачивание по линкам исходников версии не давали полный комплект файлов. Все время чего-то не хватало. Так вот, чтобы хватало, берите 2.5 и конкретно файл google-api-php-client-2.5.0.zip оттуда, а не исходники.
Необходимо упомянуть, что я еще включил API в консоли точно не могу сказать, что это обязательно. Однако, включил и с этим работает. Заодно и позволяет видеть, что оно работает.
Задавайте вопросы, если что-то не описал, поправляйте…
<?php require_once '/var/www/hotcareers/postjobs/google-api-php-client-master/vendor/autoload.php'; $client = new Google_Client(); $client->setAuthConfig('/var/www/hotcareers/postjobs/seventh-jet-242611-0697dbaff325.json'); $client->addScope('https://www.googleapis.com/auth/indexing'); $httpClient = $client->authorize(); $endpoint = 'https://indexing.googleapis.com/v3/urlNotifications:publish'; $content = '{ url: "https://careers.wipro.com/share-search-for-jobs.aspx?jobcode=938814", type: "URL_UPDATED" }'; $response = $httpClient->post($endpoint,['body'=>$content]); $status_code = $response->getStatusCode(); echo"<pre>"; print_r($response); ?>
This is my code and while executing this i am getting the below response.
GuzzleHttpPsr7Response Object ( [reasonPhrase:GuzzleHttpPsr7Response:private] => Forbidden [statusCode:GuzzleHttpPsr7Response:private] => 403 [headers:GuzzleHttpPsr7Response:private] => Array ( [Vary] => Array ( [0] => X-Origin [1] => Referer [2] => Origin,Accept-Encoding ) [Content-Type] => Array ( [0] => application/json; charset=UTF-8 ) [Date] => Array ( [0] => Wed, 12 Jun 2019 06:38:14 GMT ) [Server] => Array ( [0] => ESF ) [Cache-Control] => Array ( [0] => private ) [X-XSS-Protection] => Array ( [0] => 0 ) [X-Frame-Options] => Array ( [0] => SAMEORIGIN ) [X-Content-Type-Options] => Array ( [0] => nosniff ) [Alt-Svc] => Array ( [0] => quic=":443"; ma=2592000; v="46,44,43,39" ) [Accept-Ranges] => Array ( [0] => none ) [Transfer-Encoding] => Array ( [0] => chunked ) ) [headerNames:GuzzleHttpPsr7Response:private] => Array ( [vary] => Vary [content-type] => Content-Type [date] => Date [server] => Server [cache-control] => Cache-Control [x-xss-protection] => X-XSS-Protection [x-frame-options] => X-Frame-Options [x-content-type-options] => X-Content-Type-Options [alt-svc] => Alt-Svc [accept-ranges] => Accept-Ranges [transfer-encoding] => Transfer-Encoding ) [protocol:GuzzleHttpPsr7Response:private] => 1.1 [stream:GuzzleHttpPsr7Response:private] => GuzzleHttpPsr7Stream Object ( [stream:GuzzleHttpPsr7Stream:private] => Resource id #11 [size:GuzzleHttpPsr7Stream:private] => [seekable:GuzzleHttpPsr7Stream:private] => 1 [readable:GuzzleHttpPsr7Stream:private] => 1 [writable:GuzzleHttpPsr7Stream:private] => 1 [uri:GuzzleHttpPsr7Stream:private] => php://temp [customMetadata:GuzzleHttpPsr7Stream:private] => Array ( ) ) )
I am having a property in google console and have created a service account and it got verified. but, while executing the script i am unable to post the url. Please help with a solution. thanks in advance
Я пытаюсь отправить запрос POST через API индексации Google, но получаю HTTP erro 403 (запрещено).
Мой код ниже:
require_once '../google-api-php-client-2.2.2/vendor/autoload.php';
$client = new Google_Client();
$client->setDeveloperKey('xxxxxxxxxxxxxx');
$client->setAuthConfig('xxxxxxxxxxxxx.json');
$client->addScope('https://www.googleapis.com/auth/indexing');
$httpClient = $client->authorize();
$endpoint = 'https://indexing.googleapis.com/v3/urlNotifications:publish?key=xxxxxxxxxx';
$content = "{
"url": "https://www.example.com/whatever.html",
"type": "URL_UPDATED"}";
$response = $httpClient->post($endpoint, [ 'body' => $content ]);
$status_code = $response->getStatusCode();
die('I am done...: ' . $status_code);
Мой полный ответ таков:
GuzzleHttpPsr7Response Object
(
[reasonPhrase:GuzzleHttpPsr7Response:private] => Forbidden
[statusCode:GuzzleHttpPsr7Response:private] => 403
[headers:GuzzleHttpPsr7Response:private] => Array
(
[Vary] => Array
(
[0] => X-Origin
[1] => Referer
[2] => Origin,Accept-Encoding
)
[Content-Type] => Array
(
[0] => application/json; charset=UTF-8
)
[Date] => Array
(
[0] => Sat, 09 Feb 2019 23:13:30 GMT
)
[Server] => Array
(
[0] => ESF
)
[Cache-Control] => Array
(
[0] => private
)
[X-XSS-Protection] => Array
(
[0] => 1; mode=block
)
[X-Frame-Options] => Array
(
[0] => SAMEORIGIN
)
[X-Content-Type-Options] => Array
(
[0] => nosniff
)
[Alt-Svc] => Array
(
[0] => quic=":443"; ma=2592000; v="44,43,39")
[Accept-Ranges] => Array
(
[0] => none
)
[Transfer-Encoding] => Array
(
[0] => chunked
)
)
[headerNames:GuzzleHttpPsr7Response:private] => Array
(
[vary] => Vary
[content-type] => Content-Type
[date] => Date
[server] => Server
[cache-control] => Cache-Control
[x-xss-protection] => X-XSS-Protection
[x-frame-options] => X-Frame-Options
[x-content-type-options] => X-Content-Type-Options
[alt-svc] => Alt-Svc
[accept-ranges] => Accept-Ranges
[transfer-encoding] => Transfer-Encoding
)
[protocol:GuzzleHttpPsr7Response:private] => 1.1
[stream:GuzzleHttpPsr7Response:private] => GuzzleHttpPsr7Stream Object
(
[stream:GuzzleHttpPsr7Stream:private] => Resource id #84
[size:GuzzleHttpPsr7Stream:private] =>
[seekable:GuzzleHttpPsr7Stream:private] => 1
[readable:GuzzleHttpPsr7Stream:private] => 1
[writable:GuzzleHttpPsr7Stream:private] => 1
[uri:GuzzleHttpPsr7Stream:private] => php://temp
[customMetadata:GuzzleHttpPsr7Stream:private] => Array
(
)
)
)
Я понимаю, что означает «Запрещено», но не могу понять, ПОЧЕМУ я получаю ошибку. Я следовал инструкциям по настройке. Я настроил ключ API. Я даже установил его без ограничений для начала (конечно, я ограничу его позже), я настроил ключи учетной записи службы, файл json существует там, где я его называю (без него я получаю ошибку 401, а не 403 ) и, глядя на справку по использованию ключей API, я передаю ключ правильно.
Что мне не хватает?
2
Решение
Если вы получаете ошибку 403, вам, скорее всего, просто нужно добавить учетную запись службы, которую вы используете в качестве владельца, в Google Search Console.
Вы можете найти инструкции и или информацию Вот
1
Другие решения
Других решений пока нет …
I’m attempting to do a post for google Real Time Indexing. I’m simply attempting to send an empty atom to google — I’m mainly testing the shell for what will be an amp post in th efuture. I’m getting the following error for my empty atom post:
"error": {
"code": 403,
"message": "Google Indexing API has not been used in project api-project-xxx before or it is disabled.
Enable it by visiting https://console.developers.google.com/apis/api/indexing.googleapis.com/overview?project=api-project-xxx then retry.
If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry."
}
I followed the link above and saw that I don’t have a permission to view what’s there… I was given a .json api-project file that I thought would work as an authentication file, I’m not sure if the issue is with using the «api-project.json» file or something else. Here is my basic script producing the above error:
String scopes = "https://www.googleapis.com/auth/indexing";
String endPoint = "https://indexing.googleapis.com/xxx...";
genericUrl = new GenericUrl(endPoint);
httpTransport = GoogleNetHttpTransport.newTrustedTransport();
requestFactory = httpTransport.createRequestFactory();
jsonFactory = new JacksonFactory();
InputStream in = IOUtils.toInputStream("api-project.json");
String atom = "< ... basic atom shell is here .... >"
request = requestFactory.buildPostRequest(genericUrl, ByteArrayContent.fromString(null, atom));
credentials = GoogleCredential.fromStream(in, httpTransport, jsonFactory).createScoped(Collections.singleton(scopes));
credentials.initialize(request);
HttpResponse response = request.execute();
Any guidance here will be much appreciated. Thanks a lot.
I’m attempting to do a post for google Real Time Indexing. I’m simply attempting to send an empty atom to google — I’m mainly testing the shell for what will be an amp post in th efuture. I’m getting the following error for my empty atom post:
"error": {
"code": 403,
"message": "Google Indexing API has not been used in project api-project-xxx before or it is disabled.
Enable it by visiting https://console.developers.google.com/apis/api/indexing.googleapis.com/overview?project=api-project-xxx then retry.
If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry."
}
I followed the link above and saw that I don’t have a permission to view what’s there… I was given a .json api-project file that I thought would work as an authentication file, I’m not sure if the issue is with using the «api-project.json» file or something else. Here is my basic script producing the above error:
String scopes = "https://www.googleapis.com/auth/indexing";
String endPoint = "https://indexing.googleapis.com/xxx...";
genericUrl = new GenericUrl(endPoint);
httpTransport = GoogleNetHttpTransport.newTrustedTransport();
requestFactory = httpTransport.createRequestFactory();
jsonFactory = new JacksonFactory();
InputStream in = IOUtils.toInputStream("api-project.json");
String atom = "< ... basic atom shell is here .... >"
request = requestFactory.buildPostRequest(genericUrl, ByteArrayContent.fromString(null, atom));
credentials = GoogleCredential.fromStream(in, httpTransport, jsonFactory).createScoped(Collections.singleton(scopes));
credentials.initialize(request);
HttpResponse response = request.execute();
Any guidance here will be much appreciated. Thanks a lot.
Вы создали проект в Google Cloud Platform. Создали Consent Screen для OAuth2.0 Client ID. Создали приложение, которое должно, используя SDK (допустим google-api-php-client ) запрашивать у пользователя разрешения. Однако пользователь видит вот такое сообщение.

Что это значит и что с этим делать.
Что значит Ошибка 403: access_denied для Google API
Дело в том, что проект в Google Cloud Platform по умолчанию находится в режиме тестирования. И чтобы пользоваться функционалом разных API Google требующего OAuth авторизации нужно либо пройти модерацию проекта в Google, либо добавить тестовых пользователей (аккаунты google этих пользователей) в специальный список тестеров для OAuth2.0 Client ID в раздел OAuth consent screen. Если этого не сделать или запрашивать разрешения у пользователя не из этого списка то как раз и будет появляться ошибка Ошибка 403: access_denied.
Как добавить тестового пользователя в OAuth2.0 Client ID
Открой раздел OAuth consent screen (ссылка вида
https://console.cloud.google.com/apis/credentials/consent?project=<твой проект> ) и найди кнопку Test Users

Добавь тестового юзера используя его емейл на домене gmail.com вида
some—user@gmail.com , чтобы получилось так:

Тогда этот пользователь при запросе разрешений из твоего разрешения перестанет получать ошибку Ошибка 403: access_denied. А вместо него будет вот такое окошко:

Оно как раз рассказывает пользователю, которого вы добавили в список тестеров, что приложение которое запрашивает у пользователя разрешения к его ресурсам не было проверено в Google и может быть не безопасно. То есть продакшен на широкую публику такого приложения вызывает большие сомнения.
Но если пользователь согласится, то:

Затем выбери нужные права

И все заработает. Только не забудь, что для каждого проекта есть лимит в 100 пользователей которые могут стать тестерами. И, самое главное, тестеров нельзя удалить из списка!
А ещё, если у вас на один аккаунт выданы разрешения на управление другими аккаунтами (например для YouTube), то достаточно добавить в тестеры такой метааккаунт чтобы получить доступ ко всем аккаунтам (каналам Youtube например) к которым имеет доступ такой аккаунт.