diff --git a/packages/govuk-frontend/src/govuk/components/address/README.md b/packages/govuk-frontend/src/govuk/components/address/README.md
new file mode 100644
index 0000000000..a76e04fd50
--- /dev/null
+++ b/packages/govuk-frontend/src/govuk/components/address/README.md
@@ -0,0 +1,15 @@
+# Address
+
+## Installation
+
+See the [main README quick start guide](https://github.com/alphagov/govuk-frontend#quick-start) for how to install this component.
+
+## Guidance and Examples
+
+Find out when to use the address component in your service in the [GOV.UK Design System](https://design-system.service.gov.uk/components/address).
+
+## Component options
+
+Use options to customise the appearance, content and behaviour of a component when using a macro, for example, changing the text.
+
+See [options table](https://design-system.service.gov.uk/components/address/#options-address-example) for details.
diff --git a/packages/govuk-frontend/src/govuk/components/address/address.yaml b/packages/govuk-frontend/src/govuk/components/address/address.yaml
new file mode 100644
index 0000000000..6c476d4908
--- /dev/null
+++ b/packages/govuk-frontend/src/govuk/components/address/address.yaml
@@ -0,0 +1,243 @@
+params:
+ - name: legend
+ type: object
+ required: true
+ description: The legend for the address component.
+ params:
+ - name: text
+ type: string
+ required: true
+ description: If `html` is set, this is not required. Text to use within the legend. If `html` is provided, the `text` option will be ignored.
+ - name: html
+ type: string
+ required: true
+ description: If `text` is set, this is not required. HTML to use within the legend. If `html` is provided, the `text` option will be ignored.
+ - name: classes
+ type: string
+ required: false
+ description: Classes to add to the legend.
+ - name: isPageHeading
+ type: boolean
+ required: false
+ description: Whether the legend also acts as the heading for the page.
+ - name: line1
+ type: object
+ required: true
+ description: Line 1 of the address
+ params:
+ - name: id
+ type: string
+ required: true
+ description: The ID of the address line 1 field.
+ - name: label
+ type: object
+ required: false
+ description: The label used by address line 1. Defaults to "Line 1".
+ isComponent: true
+ - name: line2
+ type: object
+ required: true
+ description: Line 2 of the address
+ params:
+ - name: id
+ type: string
+ required: true
+ description: The ID of the address line 2 field.
+ - name: label
+ type: object
+ required: false
+ description: The label used by address line 2. Defaults to "Line 2".
+ isComponent: true
+ - name: visuallyHiddenText
+ type: boolean
+ required: false
+ description: Optional field to hide the label of line 2 and use hidden text.
+ - name: townOrCity
+ type: object
+ required: true
+ description: Town/city of the address
+ params:
+ - name: id
+ type: string
+ required: true
+ description: The ID of town/city field.
+ - name: label
+ type: object
+ required: false
+ description: The label used by town/city. Defaults to "Town or city".
+ isComponent: true
+ - name: county
+ type: object
+ required: true
+ description: County of the address
+ params:
+ - name: id
+ type: string
+ required: true
+ description: The ID of the county field.
+ - name: label
+ type: object
+ required: false
+ description: The label used by county. Defaults to "County".
+ isComponent: true
+ - name: postcode
+ type: object
+ required: true
+ description: Postcode of the address
+ params:
+ - name: id
+ type: string
+ required: true
+ description: The ID of the postcode field.
+ - name: label
+ type: object
+ required: false
+ description: The label used by postcode. Defaults to "Postcode".
+ isComponent: true
+ - name: values
+ type: object
+ required: false
+ description: Values to pre-populate the address fields with. If an object contains a matching field ID, the value will be used in the text input.
+ - name: errorMessages
+ type: object
+ required: false
+ description: Error messages for each address field. If an object contains a matching field ID, the error will be rendered by the text input.
+
+examples:
+ - name: default
+ options:
+ legend:
+ text: 'What is your address?'
+ line1:
+ id: 'line1'
+ line2:
+ id: 'line2'
+ townOrCity:
+ id: 'townOrCity'
+ county:
+ id: 'county'
+ postcode:
+ id: 'postcode'
+
+ - name: with error messages
+ options:
+ legend:
+ text: 'Where do you live?'
+ line1:
+ id: 'line1'
+ line2:
+ id: 'line2'
+ townOrCity:
+ id: 'townOrCity'
+ county:
+ id: 'county'
+ postcode:
+ id: 'postcode'
+ errorMessages:
+ line1:
+ text: Enter address line 1
+ townOrCity:
+ text: Enter town or city
+ county:
+ text: Enter county
+ postcode:
+ text: Enter postcode
+
+ - name: with required and optional error messages
+ options:
+ legend:
+ text: 'What is your current address?'
+ line1:
+ id: 'line1'
+ line2:
+ id: 'line2'
+ townOrCity:
+ id: 'townOrCity'
+ county:
+ id: 'county'
+ postcode:
+ id: 'postcode'
+ values:
+ line2: Line 2!
+ errorMessages:
+ line1:
+ text: Enter address line 1
+ line2:
+ text: Address line 2 must not contain special characters
+ townOrCity:
+ text: Enter town or city
+ county:
+ text: Enter county
+ postcode:
+ text: Enter postcode
+
+ - name: with submitted values and partial error messages
+ options:
+ legend:
+ text: 'What is your address?'
+ line1:
+ id: 'line1'
+ line2:
+ id: 'line2'
+ townOrCity:
+ id: 'townOrCity'
+ county:
+ id: 'county'
+ postcode:
+ id: 'postcode'
+ values:
+ line1: Line 1!
+ county: London
+ errorMessages:
+ line1:
+ text: Address line 1 cannot contain special characters
+ townOrCity:
+ text: Enter town or city
+ postcode:
+ text: Enter postcode
+
+ - name: with hidden line 2 label
+ options:
+ legend:
+ text: 'What is your address?'
+ line1:
+ id: 'line1'
+ label: 'Building and street'
+ line2:
+ id: 'line2'
+ visuallyHiddenText: true
+ townOrCity:
+ id: 'townOrCity'
+ county:
+ id: 'county'
+ postcode:
+ id: 'postcode'
+
+ - name: with hidden line 2 label, submitted values and error messages
+ options:
+ legend:
+ text: 'What is your address?'
+ line1:
+ id: 'line1'
+ label: 'Building and street'
+ line2:
+ id: 'line2'
+ visuallyHiddenText: true
+ townOrCity:
+ id: 'townOrCity'
+ county:
+ id: 'county'
+ postcode:
+ id: 'postcode'
+ values:
+ line1: Line 1
+ postcode: W1A
+ errorMessages:
+ line2:
+ text: Enter a value
+ townOrCity:
+ text: Enter town or city
+ county:
+ text: Enter county
+ postcode:
+ text: Postcode is too short
diff --git a/packages/govuk-frontend/src/govuk/components/address/macro.njk b/packages/govuk-frontend/src/govuk/components/address/macro.njk
new file mode 100644
index 0000000000..855ab7baf8
--- /dev/null
+++ b/packages/govuk-frontend/src/govuk/components/address/macro.njk
@@ -0,0 +1,3 @@
+{% macro govukAddress(params) %}
+ {%- include "./template.njk" -%}
+{% endmacro %}
diff --git a/packages/govuk-frontend/src/govuk/components/address/template.njk b/packages/govuk-frontend/src/govuk/components/address/template.njk
new file mode 100644
index 0000000000..bfeb50576d
--- /dev/null
+++ b/packages/govuk-frontend/src/govuk/components/address/template.njk
@@ -0,0 +1,110 @@
+{% from "../../macros/attributes.njk" import govukAttributes -%}
+{% from "../fieldset/macro.njk" import govukFieldset %}
+{% from "../input/macro.njk" import govukInput %}
+
+{% set legend = params.legend %}
+{% set line1 = params.line1 %}
+{% set line2 = params.line2 %}
+{% set townOrCity = params.townOrCity %}
+{% set county = params.county %}
+{% set postcode = params.postcode %}
+{% set values = params.values %}
+{% set errorMessages = params.errorMessages %}
+
+{% set defaultLine1Label = "Line 1" %}
+{% set defaultLine2Label = "Line 2" %}
+{% set defaultTownCityLabel = "Town or city" %}
+{% set defaultCountyLabel = "County" %}
+{% set defaultPostcodeLabel = "Postcode" %}
+
+{% set line2LabelVisuallyHidden = line2.visuallyHiddenText %}
+
+{% if line2LabelVisuallyHidden %}
+ {% set line1VisuallyHiddenText %}
+ {{ line1.label or defaultLine1Label }} line 1 of 2
+ {% endset %}
+
+ {% set line2VisuallyHiddenText %}
+ {{ line1.label or defaultLine1Label }} line 2 of 2
+ {% endset %}
+
+{% endif %}
+
+{% call govukFieldset({
+ legend: {
+ text: legend.text,
+ html: legend.html,
+ classes: legend.classes or "govuk-fieldset__legend--l",
+ isPageHeading: legend.isPageHeading
+ }
+}) %}
+ {{ govukInput({
+ label: {
+ text: not line2LabelVisuallyHidden and line1.label or defaultLine1Label,
+ html: line2LabelVisuallyHidden and line1VisuallyHiddenText
+ },
+ id: line1.id,
+ name: line1.id,
+ value: values[line1.id],
+ type: "text",
+ errorMessage: errorMessages[line1.id] and {
+ text: errorMessages[line1.id].text
+ }
+ }) }}
+
+ {{ govukInput({
+ label: {
+ text: not line2LabelVisuallyHidden and line2.label or defaultLine2Label,
+ html: line2LabelVisuallyHidden and line2VisuallyHiddenText
+ },
+ id: line2.id,
+ name: line2.id,
+ value: values[line2.id],
+ type: "text",
+ errorMessage: errorMessages[line2.id] and {
+ text: errorMessages[line2.id].text
+ }
+ }) }}
+
+ {{ govukInput({
+ label: {
+ text: townOrCity.label or defaultTownCityLabel
+ },
+ id: townOrCity.id,
+ classes: "govuk-!-width-two-thirds",
+ name: townOrCity.id,
+ value: values[townOrCity.id],
+ type: "text",
+ errorMessage: errorMessages[townOrCity.id] and {
+ text: errorMessages[townOrCity.id].text
+ }
+ }) }}
+
+ {{ govukInput({
+ label: {
+ text: county.label or defaultCountyLabel
+ },
+ id: county.id,
+ classes: "govuk-!-width-two-thirds",
+ name: county.id,
+ value: values[county.id],
+ type: "text",
+ errorMessage: errorMessages[county.id] and {
+ text: errorMessages[county.id].text
+ }
+ }) }}
+
+ {{ govukInput({
+ label: {
+ text: postcode.label or defaultPostcodeLabel
+ },
+ id: postcode.id,
+ classes: "govuk-input--width-10",
+ name: postcode.id,
+ value: values[postcode.id],
+ type: "text",
+ errorMessage: errorMessages[postcode.id] and {
+ text: errorMessages[postcode.id].text
+ }
+ }) }}
+{% endcall %}