I am trying to read the contents of a Google Docs file by using the JavaScript googleapis
API. The file exists and I can send the request, but I get a 404 error when reading the contents.
To reproduce:
- Create a Google Cloud project as described in Create Google Cloud project
- In the Google project, enable the Google Docs API
- Create a service account with
Owner
role - Edit the service account to create a
json
service account key - Run the following
Node.js
code to get a 404 error:
const { google } = require("googleapis")
const auth = new google.auth.GoogleAuth({
keyFile: "<path_to_service_account_key_json_file>",
scopes: [
"https://www.googleapis.com/auth/documents"
]
})
async function getDocumentContents(documentId) {
try {
const authClient = await auth.getClient()
const docs = google.docs({ version: "v1", auth: authClient })
const response = await docs.documents.get({ documentId })
return response.data
} catch (error) {
console.error(error)
}
}
(async () => {
const documentId = "2PACX-1vRMx5YQlZNa3ra8dYYxmv-QIQ3YJe8tbI3kqcuC7lQiZm-CSEznKfN_HYNSpoXcZIV3Y_O3YoUB1ecq"
const documentContents = await getDocumentContents(documentId)
console.info(documentContents.body.content)
})()
I would expect the file contents of this file to be printed to the console, but instead I get a 404 error. What am I missing?
This is the full error message:
GaxiosError: Requested entity was not found.
at Gaxios._request (<path>/node_modules/gaxios/build/src/gaxios.js:142:23)
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
at async JWT.requestAsync (<path>/node_modules/google-auth-library/build/src/auth/oauth2client.js:429:18)
at async getDocumentContents (<path>/<file_name>.cjs:25:26)
at async <path>/<file_name>.cjs:36:30 {
config: {
url: 'https://docs.googleapis.com/v1/documents/2PACX-1vRMx5YQlZNa3ra8dYYxmv-QIQ3YJe8tbI3kqcuC7lQiZm-CSEznKfN_HYNSpoXcZIV3Y_O3YoUB1ecq',
method: 'GET',
apiVersion: '',
userAgentDirectives: [ [Object] ],
paramsSerializer: [Function (anonymous)],
headers: {
'x-goog-api-client': 'gdcl/7.2.0 gl-node/22.11.0',
'Accept-Encoding': 'gzip',
'User-Agent': 'google-api-nodejs-client/7.2.0 (gzip)',
Authorization: '<<REDACTED> - See `errorRedactor` option in `gaxios` for configuration>.'
},
params: {},
validateStatus: [Function (anonymous)],
retry: true,
responseType: 'unknown',
errorRedactor: [Function: defaultErrorRedactor],
retryConfig: {
currentRetryAttempt: 0,
retry: 3,
httpMethodsToRetry: [Array],
noResponseRetries: 2,
retryDelayMultiplier: 2,
timeOfFirstRequest: 1735753900182,
totalTimeout: 9007199254740991,
maxRetryDelay: 9007199254740991,
statusCodesToRetry: [Array]
}
},
response: {
config: {
url: 'https://docs.googleapis.com/v1/documents/2PACX-1vRMx5YQlZNa3ra8dYYxmv-QIQ3YJe8tbI3kqcuC7lQiZm-CSEznKfN_HYNSpoXcZIV3Y_O3YoUB1ecq',
method: 'GET',
apiVersion: '',
userAgentDirectives: [Array],
paramsSerializer: [Function (anonymous)],
headers: [Object],
params: {},
validateStatus: [Function (anonymous)],
retry: true,
responseType: 'unknown',
errorRedactor: [Function: defaultErrorRedactor]
},
data: { error: [Object] },
headers: {
'alt-svc': 'h3=":443"; ma=2592000,h3-29=":443"; ma=2592000',
'content-encoding': 'gzip',
'content-type': 'application/json; charset=UTF-8',
date: 'Wed, 01 Jan 2025 17:51:40 GMT',
server: 'ESF',
'transfer-encoding': 'chunked',
vary: 'Origin, X-Origin, Referer',
'x-content-type-options': 'nosniff',
'x-frame-options': 'SAMEORIGIN',
'x-l2-request-path': 'l2-managed-5',
'x-xss-protection': '0'
},
status: 404,
statusText: 'Not Found',
request: {
responseURL: 'https://docs.googleapis.com/v1/documents/2PACX-1vRMx5YQlZNa3ra8dYYxmv-QIQ3YJe8tbI3kqcuC7lQiZm-CSEznKfN_HYNSpoXcZIV3Y_O3YoUB1ecq'
}
},
error: undefined,
status: 404,
code: 404,
errors: [
{
message: 'Requested entity was not found.',
domain: 'global',
reason: 'notFound'
}
],
[Symbol(gaxios-gaxios-error)]: '6.7.1'
}
2
Answers
It seems the problem is that the Google Docs API doesn't allow access to published docs, only to docs that are shared with the appropriate permissions. So a workaround for accessing a published doc is to copy its contents to a shared doc and then access this doc instead.
to access the file you need to share the file to the service account to do that you need to:
Find your service account email from your JSON credentials file – it looks like: [email protected]
Open your Google Doc in the browser
Click the "Share" button in the top right
Add the service account email as an editor/viewer
Make sure to check these settings:
"Notify people" should be unchecked
Click "Send" or "Share" to confirm
hopes it work