---
description: Upload, update, and delete custom certificates.
title: Manage custom certificates
image: https://developers.cloudflare.com/og-docs.png
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ssl/llms.txt  
> Use this file to discover all available pages before exploring further.

# Manage custom certificates

Last updated Aug 24, 2026|Copy as Markdown|[View as Markdown](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/ssl/edge-certificates/custom-certificates/uploading/index.md)|[Agent setup](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/agent-setup/)

This page lists Cloudflare requirements for custom certificates and explains how to upload and update these certificates using Cloudflare dashboard or API.

## Certificate requirements

Before accepting custom certificates, Cloudflare parses them and checks for validity according to a list of requirements.

Full list of requirements

Each custom certificate you upload must:

* Be encoded in PEM format (PEM, PKCS#7, or PKCS#12). See [Converting Using OpenSSL ↗](https://www.sslshopper.com/article-most-common-openssl-commands.html) for conversion examples.
* Not have a [key file password](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/ssl/edge-certificates/custom-certificates/remove-file-key-password/).
* Not be expiring in less than 14 days from time of upload.
* Have a subject alternative name (SAN) matching at least one hostname in the zone where it is being uploaded.
* Use a private key greater than or equal to a minimum length. Currently, 2048 bit for RSA and 225 bit for ECDSA.
* Be publicly trusted by a major browser. This does not apply for certificates that specify `User Defined` as their [bundling methodology](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/ssl/edge-certificates/custom-certificates/bundling-methodologies/).
* Be one of the following certificate types:  
  * Unified Communications Certificates (UCC)
  * Extended Validation (EV)
  * Domain Validated (DV)
  * Organization Validated (OV)

---

## Upload a custom certificate

Caution

When using `compatible` or `modern` [bundling](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/ssl/edge-certificates/custom-certificates/bundling-methodologies), make sure to upload only the leaf certificate. This will allow Cloudflare to properly handle [the expiration of intermediate and root certificates](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/ssl/edge-certificates/custom-certificates/bundling-methodologies/#intermediate-and-root-certificates).

To upload a custom SSL certificate in the dashboard:

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[Go to **Edge Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. In **Edge Certificates**, select **Upload Custom SSL Certificate**.
3. Copy and paste relevant values into **SSL Certificate** and **Private key** text areas (or select **Paste from file**).  
Note  
If doing this manually, include the `---BEGIN CERTIFICATE---` and `---END CERTIFICATE---` like the placeholder text.
4. Choose the appropriate [**Bundle Method**](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/ssl/edge-certificates/custom-certificates/bundling-methodologies/).
5. Select a value for [**Private Key Restriction**](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/ssl/edge-certificates/custom-certificates/#geo-key-manager-private-key-restriction).
6. Select a value for **Legacy Client Support**, which specifies [Server Name Indication (SNI)](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/ssl/reference/browser-compatibility/#non-sni-support) support:

  * **Modern (recommended)**: SNI only
  * **Legacy**: Supports non-SNI  
  Caution  
  Custom certificates of the type `legacy_custom` are not compatible with [BYOIP](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/byoip/).
7. Select **Upload Custom Certificate**. If you see an error for `The key you provided does not match the certificate`, contact your Certificate Authority to ensure the private key matches the certificate.
8. (optional) [Add a CAA DNS record](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/ssl/edge-certificates/caa-records/).

The following call will upload a certificate for use with `app.example.com`. Cloudflare will automatically bundle the certificate with a certificate chain optimized for maximum compatibility with browsers.

Caution

Note that if you are using an ECC key generated by OpenSSL, you will need to first remove the `-----BEGIN EC PARAMETERS-----...-----END EC PARAMETERS-----` section of the file.

1. Update the file and build the payload

```sh
cat app_example_com.pem
```

```sh
-----BEGIN CERTIFICATE-----
MIIFJDCCBAygAwIBAgIQD0ifmj/Yi5NP/2gdUySbfzANBgkqhkiG9w0BAQsFADBN
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5E
...
SzSHfXp5lnu/3V08I72q1QNzOCgY1XeL4GKVcj4or6cT6tX6oJH7ePPmfrBfqI/O
OeH8gMJ+FuwtXYEPa4hBf38M5eU5xWG7
-----END CERTIFICATE-----
```

```sh
MYCERT="$(cat app_example_com.pem|perl -pe 's/\r?\n/\\n/'|sed -e 's/..$//')"
MYKEY="$(cat app_example_com.key|perl -pe 's/\r?\n/\\n/'|sed -e's/..$//')"
```

With the certificate and key saved to environment variables (using escaped newlines), build the payload:

```bash
request_body=$(< <(cat <<EOF
{
  "certificate": "$MYCERT",
  "private_key": "$MYKEY",
  "bundle_method": "ubiquitous"
}
EOF
))
```

You can optionally add [geographic restrictions ↗](https://blog.cloudflare.com/introducing-cloudflare-geo-key-manager/) that specify where your private key can physically be decrypted:

```bash
request_body=$(< <(cat <<EOF
{
  "certificate": "$MYCERT",
  "private_key": "$MYKEY",
  "bundle_method": "ubiquitous",
  "geo_restrictions": {"label": "us"}'
}
EOF
))
```

You can also enable support for legacy clients which do not include SNI in the TLS handshake.

```bash
request_body=$(< <(cat <<EOF
{
  "certificate": "$MYCERT",
  "private_key": "$MYKEY",
  "bundle_method": "ubiquitous",
  "geo_restrictions": {"label": "us"}',
  "type":"sni_custom"
}
EOF
))
```

`sni_custom` is recommended by Cloudflare. Use `legacy_custom` when a specific client requires non-SNI support. The Cloudflare API treats all Custom SSL certificates as Legacy by default.

Caution

Custom certificates of the type `legacy_custom` are not compatible with [BYOIP](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/byoip/).

1. Upload your certificate and key

Use the [POST](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/api/resources/custom%5Fcertificates/methods/create/) endpoint to upload your certificate and key.

```bash
curl https://api.cloudflare.com/client/v4/zones/{zone_id}/custom_certificates \
--header "X-Auth-Email: <EMAIL>" \
--header "X-Auth-Key: <API_KEY>" \
--header "Content-Type: application/json" \
--data "$request_body"
```

1. (Optional) Add a CAA record.

A Certificate Authority Authorization (CAA) DNS record specifies which certificate authorities (CAs) are allowed to issue certificates for a domain. This record reduces the chance of unauthorized certificate issuance and promotes standardization across your organization.

For more guidance, refer to [Create a CAA record](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/ssl/edge-certificates/caa-records/).

---

## Update or renew an existing custom certificate

To renew a custom certificate that is approaching expiry, or to replace a certificate with updated key material, follow the steps below. **This is the recommended renewal path** — it does not consume an additional certificate quota slot and avoids downtime.

Before you update an existing custom certificate, you might want to consider having active [universal](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/ssl/edge-certificates/universal-ssl/) or [advanced](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) certificates as fallback options. Go to the [**Edge Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates) page to check a list of hostnames and status of the edge certificates in your zone.

If you are on an Enterprise plan and want to update a custom (modern) certificate, also consider requesting access to [Staging environment (Beta)](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/ssl/edge-certificates/staging-environment/).

Replacing a custom certificate following these steps does not lead to any downtime. No connections will be terminated and new connections will use the new certificate. The old certificate will only actually be deleted when the new certificate is uploaded and active.

To update a certificate in the dashboard:

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[Go to **Edge Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. In **Edge Certificates**, locate a custom certificate and select it to expand.
3. Select the wrench button and choose **Replace SSL certificate and key**.
4. Follow the same steps as [upload a new certificate](#upload-a-custom-certificate).

To update a certificate using the API, send a [PATCH](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/api/resources/custom%5Fcertificates/methods/edit/) command.

Note

To update the **Private Key Restriction** setting of a certificate, you must delete and re-add the certificate — this is an exception to the recommended renewal flow above. Plan for potential downtime if no other certificate covers the same hostnames.

---

## Delete a custom certificate

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[Go to **Edge Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. In **Edge Certificates**, locate a custom certificate and select it to expand.
3. Select the cross button.
4. Select **Confirm** to delete the certificate.

Was this helpful?

YesNo

## On this page

[![](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/uploading/#page","headline":"Manage custom certificates · Cloudflare SSL/TLS docs","description":"Upload, update, and delete custom certificates.","url":"https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/uploading/","inLanguage":"en","image":"https://developers.cloudflare.com/og-docs.png","dateModified":"2026-08-24","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```
