> This page is for Data API, version v2 (default).
> For other versions, use one of these documentation indexes:
> - v2 (default): https://developers.webflow.com/data/v2.0.0/llms.txt
> - v2 Beta: https://developers.webflow.com/data/v2.0.0-beta/llms.txt
> - v1: https://developers.webflow.com/data/v1.0.0/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.webflow.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.webflow.com/_mcp/server.

# Localizing pages

> How to use Page localization APIs to localize page content in secondary locales

Webflow's Data API enables you to localize DOM content and metadata across different locales. Localizing pages requires two main steps:

1. Retrieve data from the **primary locale**
2. Update data in the **secondary locale**

## Workflows

There are two main workflows for localizing pages:

#### [DOM Content](#dom-content)

Localize text content in a secondary locale

#### [Metadata](#metadata)

Localize page titles, SEO descriptions, and Open Graph descriptions in a secondary locale

## DOM Content

The DOM content endpoints enable you to localize text for any secondary locale. The process involves the following steps:

#### Fetch primary locale content

Use the [Get page content endpoint](/data/reference/pages-and-components/pages/get-content) to retrieve the page's DOM structure and default content.

#### Translate content

Traverse the `nodes` array in the response to identify and translate all text content.

#### Update secondary locale content

Use the `localeId` parameter in your request to the [Update Page Content endpoint](/data/reference/pages-and-components/pages/update-static-content) to apply the localized content.

---

### Retrieve page content

Start by getting the content structure for a given static page. You'll need the `pageId`, which you can find by listing all pages for a site using the [list pages endpoint](/data/reference/pages-and-components/pages/list). Once you have the `pageId`, you can use the [get page content endpoint](/data/reference/pages-and-components/pages/get-content) to retrieve the content structure for the page.

##### Request

**`cURL`**

```curl cURL
curl -G https://api.webflow.com/v2/pages/<PAGE_ID>/dom \
    -H "Authorization: Bearer <token>" \
    -d limit=100 \
    -d offset=0
```

```ts title={"getPageContent.ts"}
import { WebflowClient } from "webflow-api";

// Define Webflow Client
const webflow = new WebflowClient({ accessToken: "YOUR_ACCESS_TOKEN" });

const SITE_ID = "YOUR_SITE_ID";
const PAGE_TITLE = "YOUR_PAGE_TITLE";

// List Pages
const { pages } = await webflow.pages.list(SITE_ID);

// Find Page by Title
const selectedPage = pages?.find((page) => page.title === PAGE_TITLE);

if (selectedPage) {
  // Get Page Content
  const pageContent = await webflow.pages.getContent(selectedPage.id);
  console.log(pageContent);
} else {
  console.log(`Page with title "${PAGE_TITLE}" not found.`);
}
```

**Note:**  This API will only return content for static pages. Dynamic pages, like CMS Collection templates will return an empty response.

##### Response

The response contains a `nodes` array with the page's static content. Each node includes a `type` property that defines its content type.

\


**`pageId`** `string` — required

The unique identifier for the page

---

**`nodes`** `list of objects` — required

The list of nodes that represent the static content of the page

---

**`pagination`** `object` — required

The pagination information for the response

---

**`lastUpdated`** `string` — required

The date the page was most recently updated

---

### Response (200)

```json
{
  "pageId": "658205daa3e8206a523b5ad4",
  "nodes": [
    {
      "id": "a245c12d-995b-55ee-5ec7-aa36a6cad623",
      "type": "text",
      "text": {
        "html": "<h1>The Hitchhiker's Guide to the Galaxy</h1>",
        "text": "The Hitchhiker's Guide to the Galaxy"
      },
      "attributes": {}
    },
    {
      "id": "a245c12d-995b-55ee-5ec7-aa36a6cad627",
      "type": "text",
      "text": {
        "html": "<div><h3>Don't Panic!</h3><p>Always know where your towel is.</p></div>",
        "text": null
      },
      "attributes": {
        "number": "forty two"
      }
    },
    {
      "id": "a245c12d-995b-55ee-5ec7-aa36a6cad629",
      "type": "image",
      "image": {
        "alt": "Marvin, the Paranoid Android",
        "assetId": "659595234426a9fcbad57043"
      },
      "attributes": {}
    },
    {
      "id": "a245c12d-995b-55ee-5ec7-aa36a6cad635",
      "type": "select",
      "choices": [
        {
          "value": "choice-1",
          "text": "First choice"
        },
        {
          "value": "choice-2",
          "text": "Second choice"
        }
      ],
      "attributes": {}
    },
    {
      "id": "a245c12d-995b-55ee-5ec7-aa36a6cad642",
      "type": "text-input",
      "placeholder": "Enter something here...",
      "attributes": {}
    },
    {
      "id": "a245c12d-995b-55ee-5ec7-aa36a6cad671",
      "type": "submit-button",
      "value": "Submit",
      "waitingText": "Submitting...",
      "attributes": {}
    },
    {
      "id": "a245c12d-995b-55ee-5ec7-aa36a6cad631",
      "type": "component-instance",
      "componentId": "e3410077-d7db-43e6-8889-0d7f61184424",
      "propertyOverrides": [
        {
          "propertyId": "a245c12d-995b-55ee-5ec7-aa36a6cad633",
          "type": "Plain Text",
          "label": "Catchphrase",
          "text": {
            "html": null,
            "text": "Don't Panic!"
          }
        },
        {
          "propertyId": "a245c12d-995b-55ee-5ec7-aa36a6cad635",
          "type": "Rich Text",
          "label": "Tagline",
          "text": {
            "html": "<div><p>Always know where your towel is.</p></div>",
            "text": null
          }
        }
      ]
    }
  ],
  "pagination": {
    "limit": 4,
    "offset": 0,
    "total": 4
  },
  "lastUpdated": "2016-10-24T19:42:38.929Z"
}
```

> **Note**
>
> By default, if you don't include a `localeId` in your request, the response will return content from the primary locale.

#### Nodes

The [page content endpoint](/data/reference/pages-and-components/pages/get-content) returns a list of nodes that represent static text and images available for localization. **Note:** this endpoint doesn't return the entire DOM structure of the page, but only the static content available for localization.

#### Node types

Different node types represent different kinds of content, each with its own structure and properties.

| Node type            | Description                                                                                                                                                                                                                                                                                         |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `text`               | Represents text content. Including headings, [text blocks](https://help.webflow.com/hc/en-us/articles/33961346059027-Use-text-blocks-in-Webflow), [rich text](https://help.webflow.com/hc/en-us/articles/33961256808467-Rich-text-element-overview), form labels, and other text content on a page. |
| `image`              | Represents static images on a page. It contains alt text details for accessibility and the `assetId` for fetching the actual image resource.                                                                                                                                                        |
| `text-input`         | Represents a `textinput` and `textarea` fields on a form.                                                                                                                                                                                                                                           |
| `select`             | Represents a select field and its options on a form.                                                                                                                                                                                                                                                |
| `submit-button`      | Represents a submit button on a form. It contains the button text and waiting text of the button.                                                                                                                                                                                                   |
| `search-button`      | Represents the button text of a search button on a [site search element](https://help.webflow.com/hc/en-us/articles/33961242348179-Site-search).                                                                                                                                                    |
| `component-instance` | Represents a component instance on a page. Learn more about [localizing components](/data/docs/working-with-localization/localize-components) in the guide.                                                                                                                                         |

\


#### Node properties

Each node type has a specific structure and properties that define the content it contains. However, all nodes will have the following properties:

**`id`** `string` — required

Node UUID

---

**`type`** `enum` — required

The type of the node.

\


Acceptable values: `text`, `image`, `text-input`, `select`, `submit-button`, `search-button`, `component-instance`

---

**`attributes`** `object`

The [custom attributes](https://help.webflow.com/hc/en-us/articles/33961389460115-Custom-attributes#how-to-use-cms-data-in-custom-attributes) of the node. These are typically used to store custom data on the node like `aria-labels` for accessibility or `data-w-id`.

---

\


##### Node properties by type

Each node type has a unique structure for accessing page content. For example, a `text` node contains a `text` object, which typically includes `html` and `text` properties. These properties provide context for strings that can be localized. The tabs below detail the specific properties for each node type.

\


#### Text

**`id`** `string` — required

Node UUID

---

**`type`** `enum` — required

The type of the node. `text`

---

**`text`** `object` — required

The text content of the node

#### + Show 2 properties

**`html`** `string` — required

The HTML content of the node

---

**`text`** `string` — required

The text content of the node

---

---

**`attributes`** `map from strings to strings`

The custom attributes of the node

---

**`Text node example`**

```json title="Text node example"
{
  "id": "a245c12d-995b-55ee-5ec7-aa36a6cad623",
  "type": "text",
  "text": {
    "html": "<h1>Don't Panic!</h1>",
    "text": "Don't Panic!"
  },
  "attributes": {}
},
{
  "id": "a245c12d-995b-55ee-5ec7-aa36a6cad627",
  "type": "text",
  "text": {
    "html": "<span data-w-id=\"b3107...\">$9.99</span>",
    "text": "$9.99"
  },
  "attributes": {}
}
```

> **Nested HTML tags**
>
> The `text.html` property may contain nested HTML tags with `data-w-id` attributes (e.g., `data-w-id="some-unique-identifier"`). Retain these identifiers when updating page content in secondary locales to preserve custom attributes and links on inner HTML elements.

#### Image

**`id`** `string` — required

Node UUID

---

**`type`** `enum` — required

The type of the node. `image`

---

**`image`** `object` — required

The image content of the node

#### + Show 2 properties

**`alt`** `string` — required

The alt text for the image

---

**`assetId`** `string` — required

The ID of the asset for the image

---

---

**`attributes`** `map from strings to strings`

The custom attributes of the node

---

**`Image node example`**

```json title="Image node example"
{
  "id": "a245c12d-995b-55ee-5ec7-aa36a6cad629",
  "type": "image",
  "image": {
    "alt": "Marvin, the Paranoid Android",
    "assetId": "659595234426a9fcbad57043"
  },
  "attributes": {}
}
```

> **Updating images isn't supported by the API**
>
> Currently, updating images isn't supported by the API. To update images, you'll need to update the image asset in the Webflow designer.

#### Text Input

**`id`** `string` — required

Node UUID

---

**`type`** `enum` — required

The type of the node. `text-input`

---

**`placeholder`** `string`

The placeholder text for the input field

---

**`attributes`** `map from strings to strings`

The custom attributes of the node

---

**`Text input node example`**

```json title="Text input node example"
{
  "id": "a245c12d-995b-55ee-5ec7-aa36a6cad642",
  "type": "text-input",
  "placeholder": "Enter something here...",
  "attributes": {}
}
```

#### Select

**`id`** `string` — required

Node UUID

---

**`type`** `enum` — required

The type of the node. `select`

---

**`choices`** `list of objects` — required

The choices for the select field

#### + Show 2 properties

**`value`** `string` — required

The value of the choice

---

**`text`** `string` — required

The text of the choice

---

---

**`attributes`** `map from strings to strings`

The custom attributes of the node

---

**`Select node example`**

```json title="Select node example"
{
  "id": "a245c12d-995b-55ee-5ec7-aa36a6cad635",
  "type": "select",
  "choices": [
    {
      "value": "choice-1",
      "text": "First choice"
    },
    {
      "value": "choice-2",
      "text": "Second choice"
    }
  ],
  "attributes": {}
}
```

#### Submit Button

**`id`** `string` — required

Node UUID

---

**`type`** `enum` — required

The type of the node. `submit-button`

---

**`value`** `string` — required

The text content of the button

---

**`waitingText`** `string`

The text content of the button while submitting

---

**`attributes`** `map from strings to strings`

The custom attributes of the node

---

**`Submit button node example`**

```json title="Submit button node example"
{
  "id": "a245c12d-995b-55ee-5ec7-aa36a6cad671",
  "type": "submit-button",
  "value": "Submit",
  "waitingText": "Submitting...",
  "attributes": {}
}
```

#### Component Instance

To learn more about localizing components, see the [localizing components](/data/docs/working-with-localization/localize-components) guide.

**`id`** `string` — required

Node UUID

---

**`type`** `enum` — required

The type of the node. `component-instance`

---

**`componentId`** `string` — required

The ID of the component

---

**`propertyOverrides`** `array`

The property overrides for the component instance

#### + Show 4 properties

**`propertyId`** `string` — required

The ID of the property

---

**`type`** `string` — required

The type of the property

---

**`label`** `string` — required

The label of the property

---

**`text`** `object` — required

The text content of the property

#### + Show 2 properties

**`html`** `string`

The HTML content of the property

---

**`text`** `string`

The text content of the property

---

---

---

**`Component instance node example`**

```json title="Component instance node example"
{
  "id": "a245c12d-995b-55ee-5ec7-aa36a6cad631",
  "type": "component-instance",
  "componentId": "6258612d1ee792848f805dcf",
     "propertyOverrides": [
       {
         "propertyId": "a245c12d-995b-55ee-5ec7-aa36a6cad633",
      "type": "Plain Text",
      "label": "Catchphrase",
      "text": {
        "html": null,
        "text": "Don't Panic!"
      }
       },
       {
         "propertyId": "a245c12d-995b-55ee-5ec7-aa36a6cad635",
      "type": "Rich Text",
      "label": "Tagline",
      "text": {
        "html": "<div><p>Always know where your towel is.</p></div>",
        "text": null
      }
    }
  ]
}
```

### Update page content

Once you've identified and translated the content you want to localize, you can update it using the [update page content endpoint](/data/reference/pages-and-components/pages/update-static-content). You'll need to pass in the `localeId` of the secondary locale you want to update as a query parameter, and a list of `nodes` to update in the request body.

Each node should have the `nodeId` of the node you want to update, and the node value you want to update. The node value will vary depending on the node type.

### Request

POST [https://api.webflow.com/v2/pages/\{page\_id}/dom](https://api.webflow.com/v2/pages/\{page_id}/dom)

```curl
curl -X POST "https://api.webflow.com/v2/pages/63c720f9347c2139b248e552/dom?localeId=localeId" \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{
  "nodes": [
    {
      "nodeId": "a245c12d-995b-55ee-5ec7-aa36a6cad623",
      "text": "<h1>The Hitchhiker'\''s Guide to the Galaxy</h1>"
    },
    {
      "nodeId": "a245c12d-995b-55ee-5ec7-aa36a6cad627",
      "text": "<div><h3>Don'\''t Panic!</h3><p>Always know where your towel is.</p></div>"
    },
    {
      "nodeId": "a245c12d-995b-55ee-5ec7-aa36a6cad635",
      "text": "<h1>Hello world</h1>",
      "choices": [
        {
          "value": "choice-1",
          "text": "First choice"
        },
        {
          "value": "choice-2",
          "text": "Second choice"
        }
      ]
    },
    {
      "nodeId": "a245c12d-995b-55ee-5ec7-aa36a6cad642",
      "text": "<h1>Hello world</h1>",
      "placeholder": "Enter something here..."
    },
    {
      "nodeId": "a245c12d-995b-55ee-5ec7-aa36a6cad671",
      "text": "<h1>Hello world</h1>",
      "value": "Submit",
      "waitingText": "Submitting..."
    },
    {
      "nodeId": "a245c12d-995b-55ee-5ec7-aa36a6cad629",
      "text": "<h1>Hello world</h1>",
      "propertyOverrides": [
        {
          "propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f0",
          "text": "<div><h1>Time is an <em>illusion</em></h1></div>"
        },
        {
          "propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f1",
          "text": "Life, the Universe and Everything"
        }
      ]
    }
  ]
}'
```

```typescript
import { WebflowClient } from "webflow-api";

async function main() {
    const client = new WebflowClient({
        accessToken: "YOUR_TOKEN_HERE",
    });
    await client.pages.updateStaticContent("63c720f9347c2139b248e552", {
        localeId: "localeId",
        nodes: [
            {
                nodeId: "a245c12d-995b-55ee-5ec7-aa36a6cad623",
                text: "<h1>The Hitchhiker's Guide to the Galaxy</h1>",
            },
            {
                nodeId: "a245c12d-995b-55ee-5ec7-aa36a6cad627",
                text: "<div><h3>Don't Panic!</h3><p>Always know where your towel is.</p></div>",
            },
        ],
    });
}
main();

```

```python
from webflow import Webflow, TextNodeWrite

client = Webflow(
    access_token="YOUR_TOKEN_HERE",
)

client.pages.update_static_content(
    page_id="63c720f9347c2139b248e552",
    locale_id="localeId",
    nodes=[
        TextNodeWrite(
            node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623",
            text="<h1>The Hitchhiker\'s Guide to the Galaxy</h1>",
        ),
        TextNodeWrite(
            node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627",
            text="<div><h3>Don\'t Panic!</h3><p>Always know where your towel is.</p></div>",
        )
    ],
)

```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.webflow.com/v2/pages/63c720f9347c2139b248e552/dom?localeId=localeId"

	payload := strings.NewReader("{\n  \"nodes\": [\n    {\n      \"nodeId\": \"a245c12d-995b-55ee-5ec7-aa36a6cad623\",\n      \"text\": \"<h1>The Hitchhiker's Guide to the Galaxy</h1>\"\n    },\n    {\n      \"nodeId\": \"a245c12d-995b-55ee-5ec7-aa36a6cad627\",\n      \"text\": \"<div><h3>Don't Panic!</h3><p>Always know where your towel is.</p></div>\"\n    },\n    {\n      \"nodeId\": \"a245c12d-995b-55ee-5ec7-aa36a6cad635\",\n      \"text\": \"<h1>Hello world</h1>\",\n      \"choices\": [\n        {\n          \"value\": \"choice-1\",\n          \"text\": \"First choice\"\n        },\n        {\n          \"value\": \"choice-2\",\n          \"text\": \"Second choice\"\n        }\n      ]\n    },\n    {\n      \"nodeId\": \"a245c12d-995b-55ee-5ec7-aa36a6cad642\",\n      \"text\": \"<h1>Hello world</h1>\",\n      \"placeholder\": \"Enter something here...\"\n    },\n    {\n      \"nodeId\": \"a245c12d-995b-55ee-5ec7-aa36a6cad671\",\n      \"text\": \"<h1>Hello world</h1>\",\n      \"value\": \"Submit\",\n      \"waitingText\": \"Submitting...\"\n    },\n    {\n      \"nodeId\": \"a245c12d-995b-55ee-5ec7-aa36a6cad629\",\n      \"text\": \"<h1>Hello world</h1>\",\n      \"propertyOverrides\": [\n        {\n          \"propertyId\": \"7dd14c08-2e96-8d3d-2b19-b5c03642a0f0\",\n          \"text\": \"<div><h1>Time is an <em>illusion</em></h1></div>\"\n        },\n        {\n          \"propertyId\": \"7dd14c08-2e96-8d3d-2b19-b5c03642a0f1\",\n          \"text\": \"Life, the Universe and Everything\"\n        }\n      ]\n    }\n  ]\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.webflow.com/v2/pages/63c720f9347c2139b248e552/dom?localeId=localeId")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"nodes\": [\n    {\n      \"nodeId\": \"a245c12d-995b-55ee-5ec7-aa36a6cad623\",\n      \"text\": \"<h1>The Hitchhiker's Guide to the Galaxy</h1>\"\n    },\n    {\n      \"nodeId\": \"a245c12d-995b-55ee-5ec7-aa36a6cad627\",\n      \"text\": \"<div><h3>Don't Panic!</h3><p>Always know where your towel is.</p></div>\"\n    },\n    {\n      \"nodeId\": \"a245c12d-995b-55ee-5ec7-aa36a6cad635\",\n      \"text\": \"<h1>Hello world</h1>\",\n      \"choices\": [\n        {\n          \"value\": \"choice-1\",\n          \"text\": \"First choice\"\n        },\n        {\n          \"value\": \"choice-2\",\n          \"text\": \"Second choice\"\n        }\n      ]\n    },\n    {\n      \"nodeId\": \"a245c12d-995b-55ee-5ec7-aa36a6cad642\",\n      \"text\": \"<h1>Hello world</h1>\",\n      \"placeholder\": \"Enter something here...\"\n    },\n    {\n      \"nodeId\": \"a245c12d-995b-55ee-5ec7-aa36a6cad671\",\n      \"text\": \"<h1>Hello world</h1>\",\n      \"value\": \"Submit\",\n      \"waitingText\": \"Submitting...\"\n    },\n    {\n      \"nodeId\": \"a245c12d-995b-55ee-5ec7-aa36a6cad629\",\n      \"text\": \"<h1>Hello world</h1>\",\n      \"propertyOverrides\": [\n        {\n          \"propertyId\": \"7dd14c08-2e96-8d3d-2b19-b5c03642a0f0\",\n          \"text\": \"<div><h1>Time is an <em>illusion</em></h1></div>\"\n        },\n        {\n          \"propertyId\": \"7dd14c08-2e96-8d3d-2b19-b5c03642a0f1\",\n          \"text\": \"Life, the Universe and Everything\"\n        }\n      ]\n    }\n  ]\n}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.webflow.com/v2/pages/63c720f9347c2139b248e552/dom?localeId=localeId")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"nodes\": [\n    {\n      \"nodeId\": \"a245c12d-995b-55ee-5ec7-aa36a6cad623\",\n      \"text\": \"<h1>The Hitchhiker's Guide to the Galaxy</h1>\"\n    },\n    {\n      \"nodeId\": \"a245c12d-995b-55ee-5ec7-aa36a6cad627\",\n      \"text\": \"<div><h3>Don't Panic!</h3><p>Always know where your towel is.</p></div>\"\n    },\n    {\n      \"nodeId\": \"a245c12d-995b-55ee-5ec7-aa36a6cad635\",\n      \"text\": \"<h1>Hello world</h1>\",\n      \"choices\": [\n        {\n          \"value\": \"choice-1\",\n          \"text\": \"First choice\"\n        },\n        {\n          \"value\": \"choice-2\",\n          \"text\": \"Second choice\"\n        }\n      ]\n    },\n    {\n      \"nodeId\": \"a245c12d-995b-55ee-5ec7-aa36a6cad642\",\n      \"text\": \"<h1>Hello world</h1>\",\n      \"placeholder\": \"Enter something here...\"\n    },\n    {\n      \"nodeId\": \"a245c12d-995b-55ee-5ec7-aa36a6cad671\",\n      \"text\": \"<h1>Hello world</h1>\",\n      \"value\": \"Submit\",\n      \"waitingText\": \"Submitting...\"\n    },\n    {\n      \"nodeId\": \"a245c12d-995b-55ee-5ec7-aa36a6cad629\",\n      \"text\": \"<h1>Hello world</h1>\",\n      \"propertyOverrides\": [\n        {\n          \"propertyId\": \"7dd14c08-2e96-8d3d-2b19-b5c03642a0f0\",\n          \"text\": \"<div><h1>Time is an <em>illusion</em></h1></div>\"\n        },\n        {\n          \"propertyId\": \"7dd14c08-2e96-8d3d-2b19-b5c03642a0f1\",\n          \"text\": \"Life, the Universe and Everything\"\n        }\n      ]\n    }\n  ]\n}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.webflow.com/v2/pages/63c720f9347c2139b248e552/dom?localeId=localeId', [
  'body' => '{
  "nodes": [
    {
      "nodeId": "a245c12d-995b-55ee-5ec7-aa36a6cad623",
      "text": "<h1>The Hitchhiker\'s Guide to the Galaxy</h1>"
    },
    {
      "nodeId": "a245c12d-995b-55ee-5ec7-aa36a6cad627",
      "text": "<div><h3>Don\'t Panic!</h3><p>Always know where your towel is.</p></div>"
    },
    {
      "nodeId": "a245c12d-995b-55ee-5ec7-aa36a6cad635",
      "text": "<h1>Hello world</h1>",
      "choices": [
        {
          "value": "choice-1",
          "text": "First choice"
        },
        {
          "value": "choice-2",
          "text": "Second choice"
        }
      ]
    },
    {
      "nodeId": "a245c12d-995b-55ee-5ec7-aa36a6cad642",
      "text": "<h1>Hello world</h1>",
      "placeholder": "Enter something here..."
    },
    {
      "nodeId": "a245c12d-995b-55ee-5ec7-aa36a6cad671",
      "text": "<h1>Hello world</h1>",
      "value": "Submit",
      "waitingText": "Submitting..."
    },
    {
      "nodeId": "a245c12d-995b-55ee-5ec7-aa36a6cad629",
      "text": "<h1>Hello world</h1>",
      "propertyOverrides": [
        {
          "propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f0",
          "text": "<div><h1>Time is an <em>illusion</em></h1></div>"
        },
        {
          "propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f1",
          "text": "Life, the Universe and Everything"
        }
      ]
    }
  ]
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.webflow.com/v2/pages/63c720f9347c2139b248e552/dom?localeId=localeId");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"nodes\": [\n    {\n      \"nodeId\": \"a245c12d-995b-55ee-5ec7-aa36a6cad623\",\n      \"text\": \"<h1>The Hitchhiker's Guide to the Galaxy</h1>\"\n    },\n    {\n      \"nodeId\": \"a245c12d-995b-55ee-5ec7-aa36a6cad627\",\n      \"text\": \"<div><h3>Don't Panic!</h3><p>Always know where your towel is.</p></div>\"\n    },\n    {\n      \"nodeId\": \"a245c12d-995b-55ee-5ec7-aa36a6cad635\",\n      \"text\": \"<h1>Hello world</h1>\",\n      \"choices\": [\n        {\n          \"value\": \"choice-1\",\n          \"text\": \"First choice\"\n        },\n        {\n          \"value\": \"choice-2\",\n          \"text\": \"Second choice\"\n        }\n      ]\n    },\n    {\n      \"nodeId\": \"a245c12d-995b-55ee-5ec7-aa36a6cad642\",\n      \"text\": \"<h1>Hello world</h1>\",\n      \"placeholder\": \"Enter something here...\"\n    },\n    {\n      \"nodeId\": \"a245c12d-995b-55ee-5ec7-aa36a6cad671\",\n      \"text\": \"<h1>Hello world</h1>\",\n      \"value\": \"Submit\",\n      \"waitingText\": \"Submitting...\"\n    },\n    {\n      \"nodeId\": \"a245c12d-995b-55ee-5ec7-aa36a6cad629\",\n      \"text\": \"<h1>Hello world</h1>\",\n      \"propertyOverrides\": [\n        {\n          \"propertyId\": \"7dd14c08-2e96-8d3d-2b19-b5c03642a0f0\",\n          \"text\": \"<div><h1>Time is an <em>illusion</em></h1></div>\"\n        },\n        {\n          \"propertyId\": \"7dd14c08-2e96-8d3d-2b19-b5c03642a0f1\",\n          \"text\": \"Life, the Universe and Everything\"\n        }\n      ]\n    }\n  ]\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["nodes": [
    [
      "nodeId": "a245c12d-995b-55ee-5ec7-aa36a6cad623",
      "text": "<h1>The Hitchhiker's Guide to the Galaxy</h1>"
    ],
    [
      "nodeId": "a245c12d-995b-55ee-5ec7-aa36a6cad627",
      "text": "<div><h3>Don't Panic!</h3><p>Always know where your towel is.</p></div>"
    ],
    [
      "nodeId": "a245c12d-995b-55ee-5ec7-aa36a6cad635",
      "text": "<h1>Hello world</h1>",
      "choices": [
        [
          "value": "choice-1",
          "text": "First choice"
        ],
        [
          "value": "choice-2",
          "text": "Second choice"
        ]
      ]
    ],
    [
      "nodeId": "a245c12d-995b-55ee-5ec7-aa36a6cad642",
      "text": "<h1>Hello world</h1>",
      "placeholder": "Enter something here..."
    ],
    [
      "nodeId": "a245c12d-995b-55ee-5ec7-aa36a6cad671",
      "text": "<h1>Hello world</h1>",
      "value": "Submit",
      "waitingText": "Submitting..."
    ],
    [
      "nodeId": "a245c12d-995b-55ee-5ec7-aa36a6cad629",
      "text": "<h1>Hello world</h1>",
      "propertyOverrides": [
        [
          "propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f0",
          "text": "<div><h1>Time is an <em>illusion</em></h1></div>"
        ],
        [
          "propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f1",
          "text": "Life, the Universe and Everything"
        ]
      ]
    ]
  ]] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.webflow.com/v2/pages/63c720f9347c2139b248e552/dom?localeId=localeId")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

> **Updating text nodes**
>
> When updating text nodes, pass the `text` property with the translated text, structured as the HTML content received from the Get Page Content endpoint. The HTML tag structure must remain identical to the Get Content endpoint's response.

> **Updating images isn't supported by the API**
>
> Currently, updating images isn't supported by the API. To update images, you'll need to update the image asset in the Webflow designer.

## Metadata

The metadata endpoints enable you to localize SEO and Open Graph content for any secondary locale. The process involves the following steps:

#### Retrieve primary locale metadata

Use the [Get page metadata endpoint](/data/reference/pages-and-components/pages/get-metadata) to retrieve the page's metadata.

#### Translate metadata

Translate the metadata for the secondary locale.

#### Update secondary locale metadata

Use the [Update page metadata endpoint](/data/reference/pages-and-components/pages/update-page-settings) to update the metadata for the secondary locale.

### Retrieve page metadata

First, retrieve the page metadata for the primary locale using the [Get page metadata endpoint](/data/reference/pages-and-components/pages/get-metadata).

This endpoint will return metadata shown above for the primary locale. The response includes both internal and external information about your webflow page, including unique identifiers, draft information, and publish times.

For a full list of information returned see the [Get page metadata page in the API reference](/data/reference/pages-and-components/pages/get-metadata).

##### Request

### Request

GET [https://api.webflow.com/v2/pages/\{page\_id}](https://api.webflow.com/v2/pages/\{page_id})

```curl
curl -G https://api.webflow.com/v2/pages/63c720f9347c2139b248e552 \
     -H "Authorization: Bearer <token>" \
     -d localeId=65427cf400e02b306eaa04a0 \
     -d translatable=65427cf400e02b306eaa04a0
```

```typescript
import { WebflowClient } from "webflow-api";

async function main() {
    const client = new WebflowClient({
        accessToken: "YOUR_TOKEN_HERE",
    });
    await client.pages.getMetadata("63c720f9347c2139b248e552", {
        localeId: "65427cf400e02b306eaa04a0",
        translatable: "65427cf400e02b306eaa04a0",
    });
}
main();

```

```python
from webflow import Webflow

client = Webflow(
    access_token="YOUR_TOKEN_HERE",
)

client.pages.get_metadata(
    page_id="63c720f9347c2139b248e552",
    locale_id="65427cf400e02b306eaa04a0",
    translatable="65427cf400e02b306eaa04a0",
)

```

```go
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.webflow.com/v2/pages/63c720f9347c2139b248e552?localeId=65427cf400e02b306eaa04a0&translatable=65427cf400e02b306eaa04a0"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.webflow.com/v2/pages/63c720f9347c2139b248e552?localeId=65427cf400e02b306eaa04a0&translatable=65427cf400e02b306eaa04a0")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.webflow.com/v2/pages/63c720f9347c2139b248e552?localeId=65427cf400e02b306eaa04a0&translatable=65427cf400e02b306eaa04a0")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.webflow.com/v2/pages/63c720f9347c2139b248e552?localeId=65427cf400e02b306eaa04a0&translatable=65427cf400e02b306eaa04a0', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.webflow.com/v2/pages/63c720f9347c2139b248e552?localeId=65427cf400e02b306eaa04a0&translatable=65427cf400e02b306eaa04a0");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.webflow.com/v2/pages/63c720f9347c2139b248e552?localeId=65427cf400e02b306eaa04a0&translatable=65427cf400e02b306eaa04a0")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

##### Response

### Response (200)

```json
{
  "id": "6596da6045e56dee495bcbba",
  "siteId": "6258612d1ee792848f805dcf",
  "title": "Guide to the Galaxy",
  "slug": "guide-to-the-galaxy",
  "createdOn": "2024-03-11T10:42:00.000Z",
  "lastUpdated": "2024-03-11T10:42:42.000Z",
  "archived": false,
  "draft": false,
  "canBranch": false,
  "isBranch": true,
  "branchId": "68026fa68ef6dc744c75b833",
  "seo": {
    "title": "The Ultimate Hitchhiker's Guide to the Galaxy",
    "description": "Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels."
  },
  "openGraph": {
    "title": "Explore the Cosmos with The Ultimate Guide",
    "titleCopied": false,
    "description": "Dive deep into the mysteries of the universe with your guide to everything galactic.",
    "descriptionCopied": false
  },
  "localeId": "653fd9af6a07fc9cfd7a5e57",
  "publishedPath": "/en-us/guide-to-the-galaxy"
}
```

### Update page metadata

To update metadata for a secondary locale, translate the properties listed below and include them in the request body when calling the [Update page metadata endpoint](/data/reference/pages-and-components/pages/update-page-settings).

### Schema (`request.body`)

```yaml
openapi: 3.1.0
info:
  title: API
  version: 1.0.0
paths:
  /pages/{page_id}:
    put:
      operationId: subpackagePages_update-page-settings
      summary: Update Page Metadata
      description: |
        Update Page-level metadata, including SEO and Open Graph fields.

        Required scope | `pages:write`
      tags:
        - subpackage_pages
      parameters:
        - name: page_id
          in: path
          description: Unique identifier for a Page
          required: true
          schema:
            type: string
            format: objectid
        - name: localeId
          in: query
          description: >
            Unique identifier for a specific Locale.


            [Learn more about
            localization.](/data/v2.0.0/docs/working-with-localization)
          required: false
          schema:
            type: string
      responses:
        '200':
          description: Request was successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Pages_update-page-settings_Response_200'
        '400':
          description: Request body was incorrectly formatted.
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/Update-page-settingsRequestBadRequestError
        '401':
          description: >-
            Provided access token is invalid or does not have access to
            requested resource
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/Update-page-settingsRequestUnauthorizedError
        '404':
          description: Requested resource not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Update-page-settingsRequestNotFoundError'
        '429':
          description: >-
            The rate limit of the provided access_token has been reached. Please
            have your application respect the X-RateLimit-Remaining header we
            include on API responses.
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/Update-page-settingsRequestTooManyRequestsError
        '500':
          description: We had a problem with our server. Try again later.
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/Update-page-settingsRequestInternalServerError
      requestBody:
        description: The values to update on the Page
        content:
          application/json:
            schema:
              type: object
              properties:
                title:
                  type: string
                  description: Title for the page
                slug:
                  type: string
                  description: >
                    Slug for the page.


                    **Note:** The slug field is ignored in the following cases —
                    all other fields in the same request still apply:

                    - The site's home page, collection template pages, and
                    utility pages (e.g. 404, password, search).

                    - For secondary locales, updating the slug requires an <a
                    href="https://webflow.com/feature/localization">Advanced or
                    Enterprise localization add-on plan</a>.
                seo:
                  $ref: >-
                    #/components/schemas/PagesPageIdPutRequestBodyContentApplicationJsonSchemaSeo
                  description: SEO-related fields for the Page
                openGraph:
                  $ref: >-
                    #/components/schemas/PagesPageIdPutRequestBodyContentApplicationJsonSchemaOpenGraph
                  description: Open Graph fields for the Page
tags:
  - name: subpackage_pages
servers:
  - url: https://api.webflow.com/v2
    description: Data API
components:
  schemas:
    PagesPageIdPutRequestBodyContentApplicationJsonSchemaSeo:
      type: object
      properties:
        title:
          type: string
          description: The Page title shown in search engine results
        description:
          type: string
          description: The Page description shown in search engine results
      description: SEO-related fields for the Page
      title: PagesPageIdPutRequestBodyContentApplicationJsonSchemaSeo
    PagesPageIdPutRequestBodyContentApplicationJsonSchemaOpenGraph:
      type: object
      properties:
        title:
          type: string
          description: The title supplied to Open Graph annotations
        titleCopied:
          type: boolean
          description: Indicates the Open Graph title was copied from the SEO title
        description:
          type: string
          description: The description supplied to Open Graph annotations
        descriptionCopied:
          type: boolean
          description: >-
            Indicates the Open Graph description was copied from the SEO
            description
      description: Open Graph fields for the Page
      title: PagesPageIdPutRequestBodyContentApplicationJsonSchemaOpenGraph
    PagesPageIdPutResponsesContentApplicationJsonSchemaSeo:
      type: object
      properties:
        title:
          type: string
          description: The Page title shown in search engine results
        description:
          type: string
          description: The Page description shown in search engine results
      description: SEO-related fields for the Page
      title: PagesPageIdPutResponsesContentApplicationJsonSchemaSeo
    PagesPageIdPutResponsesContentApplicationJsonSchemaOpenGraph:
      type: object
      properties:
        title:
          type: string
          description: The title supplied to Open Graph annotations
        titleCopied:
          type: boolean
          default: true
          description: Indicates the Open Graph title was copied from the SEO title
        description:
          type: string
          description: The description supplied to Open Graph annotations
        descriptionCopied:
          type: boolean
          default: true
          description: >-
            Indicates the Open Graph description was copied from the SEO
            description
      description: Open Graph fields for the Page
      title: PagesPageIdPutResponsesContentApplicationJsonSchemaOpenGraph
    Pages_update-page-settings_Response_200:
      type: object
      properties:
        id:
          type: string
          format: objectid
          description: Unique identifier for the Page
        siteId:
          type: string
          format: objectid
          description: Unique identifier for the Site
        title:
          type: string
          description: Title of the Page
        slug:
          type: string
          description: slug of the Page (derived from title)
        parentId:
          type: string
          format: objectid
          description: Identifier of the parent folder
        collectionId:
          type: string
          format: objectid
          description: >-
            Unique identifier for a linked Collection, value will be null if the
            Page is not part of a Collection.
        createdOn:
          type: string
          format: date-time
          description: The date the Page was created
        lastUpdated:
          type: string
          format: date-time
          description: The date the Page was most recently updated
        archived:
          type: boolean
          default: false
          description: Whether the Page has been archived
        draft:
          type: boolean
          default: false
          description: Whether the Page is a draft
        canBranch:
          type: boolean
          default: false
          description: >-
            Indicates whether the Page supports [Page
            Branching](https://university.webflow.com/lesson/page-branching).
            Pages that are already branches cannot be branched again.
        isBranch:
          type: boolean
          default: false
          description: >-
            Indicates whether the Page is a Branch of another Page [Page
            Branching](https://university.webflow.com/lesson/page-branching)
        branchId:
          type:
            - string
            - 'null'
          format: objectid
          description: >-
            If the Page is a Branch of another Page, this is the ID of the
            Branch
        seo:
          $ref: >-
            #/components/schemas/PagesPageIdPutResponsesContentApplicationJsonSchemaSeo
          description: SEO-related fields for the Page
        openGraph:
          $ref: >-
            #/components/schemas/PagesPageIdPutResponsesContentApplicationJsonSchemaOpenGraph
          description: Open Graph fields for the Page
        localeId:
          type:
            - string
            - 'null'
          format: objectid
          description: Unique ID of the page locale
        publishedPath:
          type: string
          description: Relative path of the published page URL
      required:
        - id
      description: The Page object
      title: Pages_update-page-settings_Response_200
    PagesPageIdPutResponsesContentApplicationJsonSchemaCode:
      type: string
      enum:
        - aeo_input_validation
        - analyze_filter_conflict
        - analyze_input_validation
        - analyze_unsupported_filter
        - bad_request
        - batch_too_large
        - before_historical_floor
        - billing_provider_unavailable
        - branch_merge_conflict
        - branch_merge_in_progress
        - branch_not_found
        - branch_publish_failed
        - branch_sync_pending
        - branch_task_not_found
        - branch_update_in_progress
        - brand_not_configured
        - cannot_invite_self
        - cannot_remove_self
        - cannot_update_user_role
        - client_seats_unavailable
        - collection_not_found
        - competitors_not_configured
        - conflict
        - conflicting_scope_filters
        - default_site_role_required
        - duplicate_collection
        - duplicate_member_in_request
        - duplicate_site_in_request
        - duplicate_user_email
        - ecommerce_not_enabled
        - end_time_too_recent
        - enterprise_provisioning_upstream_error
        - enterprise_self_provisioning_not_entitled
        - forbidden
        - forms_require_republish
        - incompatible_webhook_filter
        - insufficient_permissions
        - insufficient_seats
        - internal_error
        - invalid_auth_version
        - invalid_credentials
        - invalid_domain
        - invalid_resolution
        - invalid_site_role
        - invalid_time_range
        - invalid_user_email
        - invalid_workspace_role
        - invite_expired
        - invite_role_conflict
        - item_not_found
        - managed_by_scim
        - member_already_has_access
        - member_has_no_site_access
        - member_is_paying_client
        - member_not_found
        - member_not_removable
        - member_role_conflict
        - missing_scopes
        - no_domains
        - no_members_or_invites
        - not_authorized
        - not_enterprise_plan_site
        - not_enterprise_plan_workspace
        - optimize_before_historical_floor
        - optimize_input_validation
        - optimize_invalid_interval
        - optimize_unknown_dimension
        - optimize_unknown_goal
        - optimize_unknown_optimization
        - optimize_unsupported_group_by
        - order_not_found
        - page_cannot_branch
        - resource_not_found
        - service_unavailable
        - site_access_not_applicable_to_member
        - site_access_not_scopable_for_role
        - site_access_roles_must_match
        - site_not_in_workspace
        - site_role_id_invalid
        - site_role_id_not_allowed
        - site_role_id_required
        - site_specific_access_disabled
        - site_specific_access_not_entitled
        - time_range_too_wide
        - too_many_requests
        - unsupported_bot_provider
        - unsupported_version
        - unsupported_webhook_trigger_type
        - user_limit_reached
        - user_not_found
        - users_not_enabled
        - validation_error
        - workspace_invite_not_found
        - workspace_member_managed_by_scim
        - workspace_member_not_found
        - workspace_member_not_removable
        - workspace_role_not_grantable
      description: Error code
      title: PagesPageIdPutResponsesContentApplicationJsonSchemaCode
    PagesPageIdPutResponsesContentApplicationJsonSchemaDetailsItems:
      oneOf:
        - type: string
        - type: object
          additionalProperties:
            description: Any type
      title: PagesPageIdPutResponsesContentApplicationJsonSchemaDetailsItems
    Update-page-settingsRequestBadRequestError:
      type: object
      properties:
        code:
          $ref: >-
            #/components/schemas/PagesPageIdPutResponsesContentApplicationJsonSchemaCode
          description: Error code
        message:
          type: string
          description: Error message
        externalReference:
          type: string
          description: Link to more information
        details:
          type: array
          items:
            $ref: >-
              #/components/schemas/PagesPageIdPutResponsesContentApplicationJsonSchemaDetailsItems
          description: Array of errors
      title: Update-page-settingsRequestBadRequestError
    Update-page-settingsRequestUnauthorizedError:
      type: object
      properties:
        code:
          $ref: >-
            #/components/schemas/PagesPageIdPutResponsesContentApplicationJsonSchemaCode
          description: Error code
        message:
          type: string
          description: Error message
        externalReference:
          type: string
          description: Link to more information
        details:
          type: array
          items:
            $ref: >-
              #/components/schemas/PagesPageIdPutResponsesContentApplicationJsonSchemaDetailsItems
          description: Array of errors
      title: Update-page-settingsRequestUnauthorizedError
    Update-page-settingsRequestNotFoundError:
      type: object
      properties:
        code:
          $ref: >-
            #/components/schemas/PagesPageIdPutResponsesContentApplicationJsonSchemaCode
          description: Error code
        message:
          type: string
          description: Error message
        externalReference:
          type: string
          description: Link to more information
        details:
          type: array
          items:
            $ref: >-
              #/components/schemas/PagesPageIdPutResponsesContentApplicationJsonSchemaDetailsItems
          description: Array of errors
      title: Update-page-settingsRequestNotFoundError
    Update-page-settingsRequestTooManyRequestsError:
      type: object
      properties:
        code:
          $ref: >-
            #/components/schemas/PagesPageIdPutResponsesContentApplicationJsonSchemaCode
          description: Error code
        message:
          type: string
          description: Error message
        externalReference:
          type: string
          description: Link to more information
        details:
          type: array
          items:
            $ref: >-
              #/components/schemas/PagesPageIdPutResponsesContentApplicationJsonSchemaDetailsItems
          description: Array of errors
      title: Update-page-settingsRequestTooManyRequestsError
    Update-page-settingsRequestInternalServerError:
      type: object
      properties:
        code:
          $ref: >-
            #/components/schemas/PagesPageIdPutResponsesContentApplicationJsonSchemaCode
          description: Error code
        message:
          type: string
          description: Error message
        externalReference:
          type: string
          description: Link to more information
        details:
          type: array
          items:
            $ref: >-
              #/components/schemas/PagesPageIdPutResponsesContentApplicationJsonSchemaDetailsItems
          description: Array of errors
      title: Update-page-settingsRequestInternalServerError

```

**`cURL`**

```curl cURL
curl -X PUT https://api.webflow.com/v2/pages/<PAGE_ID>?localeId=<SECONDARY_LOCALE_ID> \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{
       "title": "Página de inicio - Mi sitio web",
       "seo": {
         "title": "Mi sitio web - Página de inicio",
         "description": "Descripción SEO en español para mejor visibilidad en buscadores"
       },
       "openGraph": {
         "title": "Mi sitio web",
         "description": "Descripción para compartir en redes sociales"
       }
     }'
```

**`Node.js`**

```javascript Node.js
const client = new WebflowClient({ accessToken: "YOUR_ACCESS_TOKEN" });
await client.pages.updatePageSettings("YOUR_PAGE_ID", {
  localeId: "SECONDARY_LOCALE_ID",
  title: "Página de inicio - Mi sitio web",
  seo: {
    title: "Mi sitio web - Página de inicio",
    description: "Descripción SEO en español para mejor visibilidad en buscadores"
  },
  openGraph: {
    title: "Mi sitio web",
    description: "Descripción para compartir en redes sociales"
  }
});
```

> **Warning**
>
> **Slug localization** is only available with specific Webflow plans:
>
> * **Localize Advanced add-on**
> * **Enterprise Localization**

## Complete localization workflow

Here's a complete example that demonstrates the full page localization process for static content (not including components):

**`Node.js`**

```javascript Node.js
const client = new WebflowClient({ accessToken: "YOUR_ACCESS_TOKEN" });

// Localize page static content and metadata
// Assume `translations` object holds page-level translations in memory for the secondary locale
async function localizePage(pageId, secondaryLocaleId, translations) {
  // 1. Get primary locale content structure
  const contentData = await client.pages.getContent(pageId);

  // 2. Prepare static content updates
  const staticUpdates = {
    nodes: contentData.nodes
      .filter(node => node.type === 'text' && translations.static[node.id])
      .map(node => ({
        nodeId: node.id,
        text: translations.static[node.id]
      }))
  };

  // 3. Update page content
  if (staticUpdates.nodes.length > 0) {
    await client.pages.updateStaticContent(pageId, {
      localeId: secondaryLocaleId,
      nodes: staticUpdates.nodes,
    });
  }

  // 4. Update page metadata
  if (translations.metadata) {
    await client.pages.updatePageSettings(pageId, {
      localeId: secondaryLocaleId,
      title: translations.metadata.title,
      seo: {
        title: translations.metadata.seo.title,
        description: translations.metadata.seo.description,
      },
      openGraph: {
        title: translations.metadata.openGraph.title,
        description: translations.metadata.openGraph.description,
      },
    });
  }
}
```

## FAQ

#### Do I need to update all nodes when updating page content?

No, you only need to include the nodes you want to update in the request body. If you don't include a node in the Update Page Content request body, that element will inherit the content from the primary locale.

#### What happens if an error occurs when updating page content?

If an error occurs when attempting to update a node on a page, the request may still return a 200 status code, but you may want to check the response body for the `errors` array to see if any errors surfaced.

#### Why can't I update page content in the primary locale with APIs?

Because the primary locale is the source of truth for content, changes must be initiated through the Webflow canvas at this time.

#### Why am I getting component-instance types in the Get Page Content response?

Component instances are included in the [Get Page Content API](https://developers.webflow.com/data/reference/pages-and-components/pages/get-content) response to provide a more wholistic view of the content on a page.

When getting page content for the primary locale, all component instances are included in the response. When getting page content for a secondary locale, only component instances with property overrides are included in the response.

Learn more in the [Components and properties](/data/docs/working-with-localization/localize-pages) guide.

#### After making updates to page content, why isnt' the content reflecting in the Webflow canvas?

When making updates to your site via Data APIs, you may need to refresh the page in order to see the changes reflect in the Webflow canvas.