diff --git a/lib/modules/datasource/conan/common.ts b/lib/modules/datasource/conan/common.ts
index bba6a0a0213af2ba3d3d885b7134d3008eb184d8..fce9a20255a83ac68eaa08bfc5d92608923dcfcd 100644
--- a/lib/modules/datasource/conan/common.ts
+++ b/lib/modules/datasource/conan/common.ts
@@ -6,7 +6,7 @@ export const defaultRegistryUrl = 'https://center2.conan.io/';
 export const datasource = 'conan';
 
 export const conanDatasourceRegex = regEx(
-  /(?<name>[a-zA-Z\-_0-9]+)\/(?<version>[^@/\n]+)(?<userChannel>@\S+\/\S+)/gim,
+  /^(?<name>[a-zA-Z\-_0-9]+)\/(?<version>[^@/\n]+)(?<userChannel>@\S+\/\S+)$/im,
 );
 
 export function getConanPackage(packageName: string): ConanPackage {
diff --git a/lib/modules/datasource/conan/index.spec.ts b/lib/modules/datasource/conan/index.spec.ts
index f12ea65847e87899acabb395f6aa9909310172e3..56c7faa5c1db71253be5b9f92c973764a3d1ecb5 100644
--- a/lib/modules/datasource/conan/index.spec.ts
+++ b/lib/modules/datasource/conan/index.spec.ts
@@ -360,6 +360,7 @@ describe('modules/datasource/conan/index', () => {
             version: '1.1.1',
           },
         ],
+        sourceUrl: 'https://fake.conan.url.com',
       });
     });
 
diff --git a/lib/modules/datasource/conan/index.ts b/lib/modules/datasource/conan/index.ts
index 8ecb40124792bb9bcbce8a8358179b06962f4b82..b944a97dc633be199c57442208633a4b6112490f 100644
--- a/lib/modules/datasource/conan/index.ts
+++ b/lib/modules/datasource/conan/index.ts
@@ -3,7 +3,6 @@ import { logger } from '../../../logger';
 import { cache } from '../../../util/cache/package/decorator';
 import { GithubHttp } from '../../../util/http/github';
 import { ensureTrailingSlash, joinUrlParts } from '../../../util/url';
-import { parseSingleYaml } from '../../../util/yaml';
 import * as allVersioning from '../../versioning';
 import { Datasource } from '../datasource';
 import type {
@@ -13,19 +12,14 @@ import type {
   ReleaseResult,
 } from '../types';
 import { isArtifactoryServer } from '../util';
+import { datasource, defaultRegistryUrl, getConanPackage } from './common';
 import {
-  conanDatasourceRegex,
-  datasource,
-  defaultRegistryUrl,
-  getConanPackage,
-} from './common';
-import type {
+  ConanCenterReleases,
   ConanJSON,
+  ConanLatestRevision,
   ConanProperties,
   ConanRevisionJSON,
-  ConanRevisionsJSON,
-  ConanYAML,
-} from './types';
+} from './schema';
 
 export class ConanDatasource extends Datasource {
   static readonly id = datasource;
@@ -62,13 +56,7 @@ export class ConanDatasource extends Datasource {
     const res = await this.githubHttp.get(url, {
       headers: { accept: 'application/vnd.github.v3.raw' },
     });
-    // TODO: use schema (#9610)
-    const doc = parseSingleYaml<ConanYAML>(res.body);
-    return {
-      releases: Object.keys(doc?.versions ?? {}).map((version) => ({
-        version,
-      })),
-    };
+    return ConanCenterReleases.parse(res.body);
   }
 
   @cache({
@@ -94,10 +82,11 @@ export class ConanDatasource extends Datasource {
       conanPackage.userAndChannel,
       '/revisions',
     );
-    const revisionRep =
-      await this.http.getJson<ConanRevisionsJSON>(revisionLookUp);
-    const revisions = revisionRep?.body.revisions;
-    return revisions?.[0].revision ?? null;
+    const { body: digest } = await this.http.getJson(
+      revisionLookUp,
+      ConanLatestRevision,
+    );
+    return digest;
   }
 
   @cache({
@@ -135,25 +124,16 @@ export class ConanDatasource extends Datasource {
       );
 
       try {
-        const rep = await this.http.getJson<ConanJSON>(lookupUrl);
-        const versions = rep?.body;
-        if (versions) {
+        const rep = await this.http.getJson(lookupUrl);
+        const conanJson = ConanJSON.parse(rep.body);
+        if (conanJson) {
           logger.trace({ lookupUrl }, 'Got conan api result');
           const dep: ReleaseResult = { releases: [] };
 
-          for (const resultString of Object.values(versions.results ?? {})) {
-            conanDatasourceRegex.lastIndex = 0;
-            const fromMatch = conanDatasourceRegex.exec(resultString);
-            if (fromMatch?.groups?.version && fromMatch?.groups?.userChannel) {
-              const version = fromMatch.groups.version;
-              if (fromMatch.groups.userChannel === userAndChannel) {
-                const result: Release = {
-                  version,
-                };
-                dep.releases.push(result);
-              }
-            }
-          }
+          const conanJsonReleases: Release[] = conanJson
+            .filter(({ userChannel }) => userChannel === userAndChannel)
+            .map(({ version }) => ({ version }));
+          dep.releases.push(...conanJsonReleases);
 
           try {
             if (isArtifactoryServer(rep)) {
@@ -182,25 +162,22 @@ export class ConanDatasource extends Datasource {
                 url,
                 `v2/conans/${conanPackage.conanName}/${latestVersion}/${conanPackage.userAndChannel}/latest`,
               );
-              const revResp =
-                await this.http.getJson<ConanRevisionJSON>(latestRevisionUrl);
-              const packageRev = revResp.body.revision;
+              const {
+                body: { revision: packageRev },
+              } = await this.http.getJson(latestRevisionUrl, ConanRevisionJSON);
 
               const [user, channel] = conanPackage.userAndChannel.split('/');
               const packageUrl = joinUrlParts(
                 `${groups.host}/artifactory/api/storage/${groups.repo}`,
                 `${user}/${conanPackage.conanName}/${latestVersion}/${channel}/${packageRev}/export/conanfile.py?properties=conan.package.url`,
               );
-              const packageUrlResp =
-                await this.http.getJson<ConanProperties>(packageUrl);
-
-              if (
-                packageUrlResp.body.properties &&
-                'conan.package.url' in packageUrlResp.body.properties
-              ) {
-                const conanPackageUrl =
-                  packageUrlResp.body.properties['conan.package.url'][0];
-                dep.sourceUrl = conanPackageUrl;
+              const { body: conanProperties } = await this.http.getJson(
+                packageUrl,
+                ConanProperties,
+              );
+              const { sourceUrl } = conanProperties;
+              if (sourceUrl) {
+                dep.sourceUrl = sourceUrl;
               }
             }
           } catch (err) {
diff --git a/lib/modules/datasource/conan/schema.ts b/lib/modules/datasource/conan/schema.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2ca42c64f9fd97e7dccfcd11048e3f6fae2a2584
--- /dev/null
+++ b/lib/modules/datasource/conan/schema.ts
@@ -0,0 +1,66 @@
+import { z } from 'zod';
+import { LooseArray, Yaml } from '../../../util/schema-utils';
+import type { ReleaseResult } from '../types';
+import { conanDatasourceRegex } from './common';
+
+export const ConanCenterReleases = Yaml.pipe(
+  z.object({
+    versions: z.record(z.string(), z.unknown()),
+  }),
+)
+  .transform(
+    ({ versions }): ReleaseResult => ({
+      releases: Object.keys(versions).map((version) => ({ version })),
+    }),
+  )
+  .nullable()
+  .catch(null);
+
+export const ConanJSON = z
+  .object({
+    results: z
+      .string()
+      .array()
+      .transform((array) =>
+        array.map((val) => val.match(conanDatasourceRegex)?.groups),
+      )
+      .pipe(
+        LooseArray(
+          z.object({
+            name: z.string(),
+            version: z.string(),
+            userChannel: z.string(),
+          }),
+        ),
+      ),
+  })
+  .transform(({ results }) => results)
+  .nullable()
+  .catch(null);
+
+export const ConanRevisionJSON = z.object({
+  revision: z.string(),
+  time: z.string(),
+});
+
+export const ConanLatestRevision = z
+  .object({ revisions: z.unknown().array() })
+  .transform(({ revisions }) => revisions[0])
+  .pipe(ConanRevisionJSON)
+  .transform(({ revision }) => revision)
+  .nullable()
+  .catch(null);
+
+export const ConanProperties = z
+  .object({
+    properties: z.object({
+      'conan.package.url': z.union([
+        z.string().transform((url) => [url]),
+        z.string().array(),
+      ]),
+    }),
+  })
+  .transform(({ properties }) => {
+    const sourceUrl = properties['conan.package.url'][0];
+    return { sourceUrl };
+  });
diff --git a/lib/modules/datasource/conan/types.ts b/lib/modules/datasource/conan/types.ts
index bb65481f5015f8665d2ddc3075d10449ac0da2da..18dda2e72854d1efdcb821e227ee358c10acffed 100644
--- a/lib/modules/datasource/conan/types.ts
+++ b/lib/modules/datasource/conan/types.ts
@@ -1,35 +1,4 @@
-export interface ConanJSON {
-  results?: Record<string, string>;
-}
-
-export interface ConanRevisionJSON {
-  revision: string;
-  time: string;
-}
-
-export interface ConanRevisionsJSON {
-  revisions?: Record<string, ConanRevisionJSON>;
-}
-
-export interface ConanYAML {
-  versions?: Record<string, unknown>;
-}
-
 export interface ConanPackage {
   conanName: string;
   userAndChannel: string;
 }
-
-export interface ConanRecipeProperties {
-  'conan.package.channel': string[];
-  'conan.package.license': string[];
-  'conan.package.name': string[];
-  'conan.package.url': string[];
-  'conan.package.user': string[];
-  'conan.package.version': string[];
-}
-
-export interface ConanProperties {
-  properties: ConanRecipeProperties;
-  uri: string;
-}