diff --git a/lib/modules/datasource/api.ts b/lib/modules/datasource/api.ts
index 84ba7fc52c5d2a4713dfa0e40a0253c80bfb588d..58b8a912233f14ba74a5f5f49ef88095419f93a1 100644
--- a/lib/modules/datasource/api.ts
+++ b/lib/modules/datasource/api.ts
@@ -6,6 +6,7 @@ import { AzurePipelinesTasksDatasource } from './azure-pipelines-tasks';
 import { BazelDatasource } from './bazel';
 import { BitbucketTagsDatasource } from './bitbucket-tags';
 import { BitriseDatasource } from './bitrise';
+import { BuildpacksRegistryDatasource } from './buildpacks-registry';
 import { CdnjsDatasource } from './cdnjs';
 import { ClojureDatasource } from './clojure';
 import { ConanDatasource } from './conan';
@@ -78,6 +79,7 @@ api.set(AzurePipelinesTasksDatasource.id, new AzurePipelinesTasksDatasource());
 api.set(BazelDatasource.id, new BazelDatasource());
 api.set(BitbucketTagsDatasource.id, new BitbucketTagsDatasource());
 api.set(BitriseDatasource.id, new BitriseDatasource());
+api.set(BuildpacksRegistryDatasource.id, new BuildpacksRegistryDatasource());
 api.set(CdnjsDatasource.id, new CdnjsDatasource());
 api.set(ClojureDatasource.id, new ClojureDatasource());
 api.set(ConanDatasource.id, new ConanDatasource());
diff --git a/lib/modules/datasource/buildpacks-registry/index.spec.ts b/lib/modules/datasource/buildpacks-registry/index.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5c386d9aadb7c2923155581f4444373b397c0a37
--- /dev/null
+++ b/lib/modules/datasource/buildpacks-registry/index.spec.ts
@@ -0,0 +1,66 @@
+import { getPkgReleases } from '..';
+import * as httpMock from '../../../../test/http-mock';
+import { BuildpacksRegistryDatasource } from '.';
+
+const baseUrl = 'https://registry.buildpacks.io/api/v1/buildpacks/';
+
+describe('modules/datasource/buildpacks-registry/index', () => {
+  describe('getReleases', () => {
+    it('processes real data', async () => {
+      httpMock
+        .scope(baseUrl)
+        .get('/heroku/python')
+        .reply(200, {
+          latest: {
+            version: '0.17.1',
+            namespace: 'heroku',
+            name: 'python',
+            description: "Heroku's buildpack for Python applications.",
+            homepage: 'https://github.com/heroku/buildpacks-python',
+            licenses: ['BSD-3-Clause'],
+            stacks: ['*'],
+            id: '75946bf8-3f6a-4af0-a757-614bebfdfcd6',
+          },
+          versions: [
+            {
+              version: '0.17.1',
+              _link:
+                'https://registry.buildpacks.io//api/v1/buildpacks/heroku/python/0.17.1',
+            },
+            {
+              version: '0.17.0',
+              _link:
+                'https://registry.buildpacks.io//api/v1/buildpacks/heroku/python/0.17.0',
+            },
+          ],
+        });
+      const res = await getPkgReleases({
+        datasource: BuildpacksRegistryDatasource.id,
+        packageName: 'heroku/python',
+      });
+      expect(res).toEqual({
+        registryUrl: 'https://registry.buildpacks.io',
+        releases: [{ version: '0.17.0' }, { version: '0.17.1' }],
+        sourceUrl: 'https://github.com/heroku/buildpacks-python',
+      });
+    });
+
+    it('returns null on empty result', async () => {
+      httpMock.scope(baseUrl).get('/heroku/empty').reply(200, {});
+      const res = await getPkgReleases({
+        datasource: BuildpacksRegistryDatasource.id,
+        packageName: 'heroku/empty',
+      });
+      expect(res).toBeNull();
+    });
+
+    it('handles not found', async () => {
+      httpMock.scope(baseUrl).get('/heroku/notexisting').reply(404);
+      const res = await getPkgReleases({
+        datasource: BuildpacksRegistryDatasource.id,
+        packageName: 'heroku/notexisting',
+      });
+      expect(res).toBeNull();
+    });
+  });
+});
diff --git a/lib/modules/datasource/buildpacks-registry/index.ts b/lib/modules/datasource/buildpacks-registry/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..bf54f00daf8b3544271ee3c21568ffa1a2ec3c1f
--- /dev/null
+++ b/lib/modules/datasource/buildpacks-registry/index.ts
@@ -0,0 +1,72 @@
+import urlJoin from 'url-join';
+import { ZodError } from 'zod';
+import { logger } from '../../../logger';
+import { cache } from '../../../util/cache/package/decorator';
+import { Result } from '../../../util/result';
+import { Datasource } from '../datasource';
+import { ReleasesConfig } from '../schema';
+import type { GetReleasesConfig, Release, ReleaseResult } from '../types';
+import { BuildpacksRegistryResponseSchema } from './schema';
+
+export class BuildpacksRegistryDatasource extends Datasource {
+  static readonly id = 'buildpacks-registry';
+
+  constructor() {
+    super(BuildpacksRegistryDatasource.id);
+  }
+
+  override readonly customRegistrySupport = false;
+
+  override readonly defaultRegistryUrls = ['https://registry.buildpacks.io'];
+
+  override readonly releaseTimestampSupport = true;
+  override readonly releaseTimestampNote =
+    'The release timestamp is determined from the `published_at` field in the results.';
+  override readonly sourceUrlSupport = 'release';
+  override readonly sourceUrlNote =
+    'The source URL is determined from the `source_code_url` field of the release object in the results.';
+
+  @cache({
+    namespace: `datasource-${BuildpacksRegistryDatasource.id}`,
+    key: ({ registryUrl, packageName }: GetReleasesConfig) =>
+      `${registryUrl}:${packageName}`,
+  })
+  async getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {
+    const result = Result.parse(config, ReleasesConfig)
+      .transform(({ packageName, registryUrl }) => {
+        const url = urlJoin(
+          registryUrl,
+          'api',
+          'v1',
+          'buildpacks',
+          packageName,
+        );
+
+        return this.http.getJsonSafe(url, BuildpacksRegistryResponseSchema);
+      })
+      .transform(({ versions, latest }): ReleaseResult => {
+        const releases: Release[] = versions;
+
+        const res: ReleaseResult = { releases };
+
+        if (latest?.homepage) {
+          res.homepage = latest.homepage;
+        }
+
+        return res;
+      });
+
+    const { val, err } = await result.unwrap();
+
+    if (err instanceof ZodError) {
+      logger.debug({ err }, 'buildpacks: validation error');
+      return null;
+    }
+
+    if (err) {
+      this.handleGenericErrors(err);
+    }
+
+    return val;
+  }
+}
diff --git a/lib/modules/datasource/buildpacks-registry/schema.spec.ts b/lib/modules/datasource/buildpacks-registry/schema.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a46bd3998fe8fe5c61edd0b4aebb19165aca287a
--- /dev/null
+++ b/lib/modules/datasource/buildpacks-registry/schema.spec.ts
@@ -0,0 +1,43 @@
+import { BuildpacksRegistryResponseSchema } from './schema';
+
+describe('modules/datasource/buildpacks-registry/schema', () => {
+  it('parses buildpack-registry schema', () => {
+    const response = {
+      latest: {
+        version: '0.17.1',
+        namespace: 'heroku',
+        name: 'python',
+        description: "Heroku's buildpack for Python applications.",
+        homepage: 'https://github.com/heroku/buildpacks-python',
+        licenses: ['BSD-3-Clause'],
+        stacks: ['*'],
+        id: '75946bf8-3f6a-4af0-a757-614bebfdfcd6',
+      },
+      versions: [
+        {
+          version: '0.2.0',
+          _link:
+            'https://registry.buildpacks.io//api/v1/buildpacks/heroku/python/0.2.0',
+        },
+        {
+          version: '0.1.0',
+          _link:
+            'https://registry.buildpacks.io//api/v1/buildpacks/heroku/python/0.1.0',
+        },
+      ],
+    };
+    expect(BuildpacksRegistryResponseSchema.parse(response)).toMatchObject({
+      latest: {
+        homepage: 'https://github.com/heroku/buildpacks-python',
+      },
+      versions: [
+        {
+          version: '0.2.0',
+        },
+        {
+          version: '0.1.0',
+        },
+      ],
+    });
+  });
+});
diff --git a/lib/modules/datasource/buildpacks-registry/schema.ts b/lib/modules/datasource/buildpacks-registry/schema.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6bc544196380ea9052fa7e16aeec966322d4d765
--- /dev/null
+++ b/lib/modules/datasource/buildpacks-registry/schema.ts
@@ -0,0 +1,17 @@
+import { z } from 'zod';
+
+/**
+ *  Response from registry.buildpacks.io
+ */
+export const BuildpacksRegistryResponseSchema = z.object({
+  latest: z
+    .object({
+      homepage: z.string().optional(),
+    })
+    .optional(),
+  versions: z
+    .object({
+      version: z.string(),
+    })
+    .array(),
+});
diff --git a/lib/modules/manager/buildpacks/extract.spec.ts b/lib/modules/manager/buildpacks/extract.spec.ts
index dedcefcbd4f68a00067363964c7829ea5bfad687..2cc8b60ebe829b029ff2e8a1e2902db8f73b7716 100644
--- a/lib/modules/manager/buildpacks/extract.spec.ts
+++ b/lib/modules/manager/buildpacks/extract.spec.ts
@@ -23,6 +23,7 @@ describe('modules/manager/buildpacks/extract', () => {
 [_]
 schema-version = "0.2"
 
+# valid cases
 [io.buildpacks]
 builder = "registry.corp/builder/noble:1.1.1"
 
@@ -36,16 +37,22 @@ uri = "buildpacks/nodejs:3.3.3"
 uri = "example/foo@1.0.0"
 
 [[io.buildpacks.group]]
-uri = "example/registry-cnb"
+uri = "urn:cnb:registry:example/bar@1.2.3"
 
 [[io.buildpacks.group]]
-uri = "urn:cnb:registry:example/foo@1.0.0"
+uri = "cnbs/some-bp@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
 
 [[io.buildpacks.group]]
-uri = "some-bp@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
+uri = "cnbs/some-bp:some-tag@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
 
 [[io.buildpacks.group]]
-uri = "cnbs/some-bp:some-tag@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
+id = "example/tee"
+version = "2.3.4"
+
+#invalid cases
+
+[[io.buildpacks.group]]
+uri = "example/registry-cnb"
 
 [[io.buildpacks.group]]
 uri = "from=builder:foobar"
@@ -54,7 +61,10 @@ uri = "from=builder:foobar"
 uri = "file://local.oci"
 
 [[io.buildpacks.group]]
-uri = "foo://fake.oci"`,
+uri = "foo://fake.oci"
+
+[[io.buildpacks.group]]
+id = "not/valid"`,
         'project.toml',
         {},
       );
@@ -84,15 +94,29 @@ uri = "foo://fake.oci"`,
           depName: 'buildpacks/nodejs',
           replaceString: 'buildpacks/nodejs:3.3.3',
         },
+        {
+          autoReplaceStringTemplate:
+            '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}',
+          datasource: 'buildpacks-registry',
+          currentValue: '1.0.0',
+          packageName: 'example/foo',
+        },
+        {
+          autoReplaceStringTemplate:
+            '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}',
+          datasource: 'buildpacks-registry',
+          currentValue: '1.2.3',
+          packageName: 'example/bar',
+        },
         {
           autoReplaceStringTemplate:
             '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}',
           currentDigest:
             'sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',
           datasource: 'docker',
-          depName: 'some-bp',
+          depName: 'cnbs/some-bp',
           replaceString:
-            'some-bp@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',
+            'cnbs/some-bp@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',
         },
         {
           autoReplaceStringTemplate:
@@ -105,6 +129,11 @@ uri = "foo://fake.oci"`,
           replaceString:
             'cnbs/some-bp:some-tag@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',
         },
+        {
+          datasource: 'buildpacks-registry',
+          currentValue: '2.3.4',
+          packageName: 'example/tee',
+        },
       ]);
     });
   });
diff --git a/lib/modules/manager/buildpacks/extract.ts b/lib/modules/manager/buildpacks/extract.ts
index c00d4a4c681e19aa0f5e86e917f1beb38746e22d..f723e6ddf2999c0b3d0252667249c28a15e87fff 100644
--- a/lib/modules/manager/buildpacks/extract.ts
+++ b/lib/modules/manager/buildpacks/extract.ts
@@ -1,13 +1,20 @@
 import is from '@sindresorhus/is';
 import { logger } from '../../../logger';
 import { regEx } from '../../../util/regex';
+import { BuildpacksRegistryDatasource } from '../../datasource/buildpacks-registry';
+import { isVersion } from '../../versioning/semver';
 import { getDep } from '../dockerfile/extract';
 import type {
   ExtractConfig,
   PackageDependency,
   PackageFileContent,
 } from '../types';
-import { type ProjectDescriptor, ProjectDescriptorToml } from './schema';
+import {
+  type ProjectDescriptor,
+  ProjectDescriptorToml,
+  isBuildpackByName,
+  isBuildpackByURI,
+} from './schema';
 
 const dockerPrefix = regEx(/^docker:\/?\//);
 const dockerRef = regEx(
@@ -20,6 +27,24 @@ function isDockerRef(ref: string): boolean {
   }
   return false;
 }
+const buildpackRegistryPrefix = 'urn:cnb:registry:';
+const buildpackRegistryId = regEx(
+  /^[a-z0-9\-.]+\/[a-z0-9\-.]+(?:@(?<version>.+))?$/,
+);
+
+function isBuildpackRegistryId(ref: string): boolean {
+  const bpRegistryMatch = buildpackRegistryId.exec(ref);
+  if (!bpRegistryMatch) {
+    return false;
+  } else if (!bpRegistryMatch.groups?.version) {
+    return true;
+  }
+  return isVersion(bpRegistryMatch.groups.version);
+}
+
+function isBuildpackRegistryRef(ref: string): boolean {
+  return isBuildpackRegistryId(ref) || ref.startsWith(buildpackRegistryPrefix);
+}
 
 function parseProjectToml(
   content: string,
@@ -76,7 +101,7 @@ export function extractPackageFile(
     is.array(descriptor.io.buildpacks.group)
   ) {
     for (const group of descriptor.io.buildpacks.group) {
-      if (group.uri && isDockerRef(group.uri)) {
+      if (isBuildpackByURI(group) && isDockerRef(group.uri)) {
         const dep = getDep(
           group.uri.replace(dockerPrefix, ''),
           true,
@@ -92,6 +117,31 @@ export function extractPackageFile(
         );
 
         deps.push(dep);
+      } else if (isBuildpackByURI(group) && isBuildpackRegistryRef(group.uri)) {
+        const dependency = group.uri.replace(buildpackRegistryPrefix, '');
+
+        if (dependency.includes('@')) {
+          const version = dependency.split('@')[1];
+          const dep: PackageDependency = {
+            datasource: BuildpacksRegistryDatasource.id,
+            currentValue: version,
+            packageName: dependency.split('@')[0],
+            autoReplaceStringTemplate:
+              '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}',
+          };
+          deps.push(dep);
+        }
+      } else if (isBuildpackByName(group)) {
+        const version = group.version;
+
+        if (version) {
+          const dep: PackageDependency = {
+            datasource: BuildpacksRegistryDatasource.id,
+            currentValue: version,
+            packageName: group.id,
+          };
+          deps.push(dep);
+        }
       }
     }
   }
diff --git a/lib/modules/manager/buildpacks/index.ts b/lib/modules/manager/buildpacks/index.ts
index 53a3dcfeb4c221678dad8e31de46c7279fe910b6..869bcd7252b86cf806ad7186932adb6dc51c3ad9 100644
--- a/lib/modules/manager/buildpacks/index.ts
+++ b/lib/modules/manager/buildpacks/index.ts
@@ -1,4 +1,5 @@
 import type { Category } from '../../../constants';
+import { BuildpacksRegistryDatasource } from '../../datasource/buildpacks-registry';
 import { DockerDatasource } from '../../datasource/docker';
 export { extractPackageFile } from './extract';
 
@@ -8,5 +9,8 @@ export const defaultConfig = {
   pinDigests: false,
 };
 
-export const categories: Category[] = ['docker'];
-export const supportedDatasources = [DockerDatasource.id];
+export const categories: Category[] = ['docker', 'ci', 'cd'];
+export const supportedDatasources = [
+  DockerDatasource.id,
+  BuildpacksRegistryDatasource.id,
+];
diff --git a/lib/modules/manager/buildpacks/readme.md b/lib/modules/manager/buildpacks/readme.md
index d2f7b6c613968a99d94e6b920087a03317d57a52..b25340bffc2431c542f07768eb15cf17a98c9103 100644
--- a/lib/modules/manager/buildpacks/readme.md
+++ b/lib/modules/manager/buildpacks/readme.md
@@ -6,7 +6,7 @@ Renovate can update a `project.toml` file if:
 - The file follows the [project descriptor specifications](https://github.com/buildpacks/spec/blob/main/extensions/project-descriptor.md)
 - The buildpack `uri` is an OCI image reference (references to a local file or buildpack registry are ignored)
 
-If you use buildpacks in the `io.buildpacks.group` array, then you _must_ configure the Docker reference (`uri`) for Renovate to work.
+**Note**: If you use buildpacks in the `io.buildpacks.group` array, then you _must_ configure the Docker reference (`uri`) for Renovate to work.
 
 ```toml title="Example of a project.toml file with Docker reference URIs"
 [_]
diff --git a/lib/modules/manager/buildpacks/schema.ts b/lib/modules/manager/buildpacks/schema.ts
index dc90371ca4ce9322ee353f4327f33cc6c5979dd9..15d5b54fa77c4c9ef5d6e91a4df7f5251802c403 100644
--- a/lib/modules/manager/buildpacks/schema.ts
+++ b/lib/modules/manager/buildpacks/schema.ts
@@ -1,10 +1,33 @@
 import { z } from 'zod';
 import { Toml } from '../../../util/schema-utils';
 
-const BuildpackGroup = z.object({
-  uri: z.string().optional(),
+const BuildpackByName = z.object({
+  id: z.string(),
+  version: z.string().optional(),
 });
 
+const BuildpackByURI = z.object({
+  uri: z.string(),
+});
+
+const BuildpackGroup = BuildpackByName.or(BuildpackByURI);
+
+type BuildpackByName = z.infer<typeof BuildpackByName>;
+type BuildpackByURI = z.infer<typeof BuildpackByURI>;
+type BuildpackGroup = z.infer<typeof BuildpackGroup>;
+
+export function isBuildpackByName(
+  group: BuildpackGroup,
+): group is BuildpackByName {
+  return 'id' in group;
+}
+
+export function isBuildpackByURI(
+  group: BuildpackGroup,
+): group is BuildpackByURI {
+  return 'uri' in group;
+}
+
 const IoBuildpacks = z.object({
   builder: z.string().optional(),
   group: z.array(BuildpackGroup).optional(),
diff --git a/lib/util/cache/package/types.ts b/lib/util/cache/package/types.ts
index d61cafdfe6f32ea443bd8aa732bb75cdbde79d59..3f5ed2659061b5af4a883b21d4564966dc3e61ad 100644
--- a/lib/util/cache/package/types.ts
+++ b/lib/util/cache/package/types.ts
@@ -34,6 +34,7 @@ export type PackageCacheNamespace =
   | 'datasource-bazel'
   | 'datasource-bitbucket-tags'
   | 'datasource-bitrise'
+  | 'datasource-buildpacks-registry'
   | 'datasource-cdnjs'
   | 'datasource-conan'
   | 'datasource-conda'