diff --git a/lib/datasource/nuget/index.spec.ts b/lib/datasource/nuget/index.spec.ts
index cca611cc4c96ec7958d45ae3ee8b7fd25a339953..3170f4c73c0ea7842f6da5b8b85d726061ca167c 100644
--- a/lib/datasource/nuget/index.spec.ts
+++ b/lib/datasource/nuget/index.spec.ts
@@ -3,7 +3,7 @@ import { getPkgReleases } from '..';
 import * as httpMock from '../../../test/http-mock';
 import * as _hostRules from '../../util/host-rules';
 import { id as versioning } from '../../versioning/nuget';
-import { id as datasource } from '.';
+import { id as datasource, parseRegistryUrl } from '.';
 
 const hostRules: any = _hostRules;
 
@@ -129,6 +129,44 @@ const configV3Multiple = {
 };
 
 describe('datasource/nuget', () => {
+  describe('parseRegistryUrl', () => {
+    beforeEach(() => {
+      jest.resetAllMocks();
+    });
+
+    it('extracts feed version from registry URL hash (v3)', () => {
+      const parsed = parseRegistryUrl('https://my-registry#protocolVersion=3');
+
+      expect(parsed.feedUrl).toEqual('https://my-registry/');
+      expect(parsed.protocolVersion).toEqual(3);
+    });
+
+    it('extracts feed version from registry URL hash (v2)', () => {
+      const parsed = parseRegistryUrl('https://my-registry#protocolVersion=2');
+
+      expect(parsed.feedUrl).toEqual('https://my-registry/');
+      expect(parsed.protocolVersion).toEqual(2);
+    });
+
+    it('defaults to v2', () => {
+      const parsed = parseRegistryUrl('https://my-registry');
+
+      expect(parsed.feedUrl).toEqual('https://my-registry/');
+      expect(parsed.protocolVersion).toEqual(2);
+    });
+
+    it('returns null for unparseable', () => {
+      const parsed = parseRegistryUrl(
+        'https://test:malfor%5Med@test.example.com'
+      );
+
+      expect(parsed.feedUrl).toEqual(
+        'https://test:malfor%5Med@test.example.com'
+      );
+      expect(parsed.protocolVersion).toBeNull();
+    });
+  });
+
   describe('getReleases', () => {
     beforeEach(() => {
       jest.resetAllMocks();
diff --git a/lib/datasource/nuget/index.ts b/lib/datasource/nuget/index.ts
index 215a9e0df031a4e927852670b124fef05d6e3eea..0b9ebb79369ab0dbf0ead86acea0194990307ae4 100644
--- a/lib/datasource/nuget/index.ts
+++ b/lib/datasource/nuget/index.ts
@@ -11,7 +11,7 @@ export const defaultRegistryUrls = [v3.getDefaultFeed()];
 export const defaultVersioning = nugetVersioning.id;
 export const registryStrategy = 'merge';
 
-function parseRegistryUrl(
+export function parseRegistryUrl(
   registryUrl: string
 ): { feedUrl: string; protocolVersion: number } {
   try {
diff --git a/lib/manager/nuget/__snapshots__/artifacts.spec.ts.snap b/lib/manager/nuget/__snapshots__/artifacts.spec.ts.snap
index 648131471c83dee79901bea61e566741e7f10d71..24488ed845f3cbc46224fde72f1a0786b198c8e8 100644
--- a/lib/manager/nuget/__snapshots__/artifacts.spec.ts.snap
+++ b/lib/manager/nuget/__snapshots__/artifacts.spec.ts.snap
@@ -28,7 +28,7 @@ exports[`updateArtifacts aborts if no lock file found 1`] = `Array []`;
 exports[`updateArtifacts authenticates at registries 1`] = `
 Array [
   Object {
-    "cmd": "dotnet nuget add source https://my-registry.example.org --configfile others/nuget/not-so-random/nuget.config --name myRegistry --username some-username --password some-password --store-password-in-clear-text",
+    "cmd": "dotnet nuget add source https://my-registry.example.org/ --configfile others/nuget/not-so-random/nuget.config --name myRegistry --username some-username --password some-password --store-password-in-clear-text",
     "options": Object {
       "cwd": "/tmp/github/some/repo",
       "encoding": "utf-8",
@@ -104,6 +104,47 @@ Array [
 ]
 `;
 
+exports[`updateArtifacts strips protocol version from feed url 1`] = `
+Array [
+  Object {
+    "cmd": "dotnet nuget add source https://my-registry.example.org/ --configfile others/nuget/not-so-random/nuget.config --name myRegistry",
+    "options": Object {
+      "cwd": "/tmp/github/some/repo",
+      "encoding": "utf-8",
+      "env": Object {
+        "HOME": "/home/user",
+        "HTTPS_PROXY": "https://example.com",
+        "HTTP_PROXY": "http://example.com",
+        "LANG": "en_US.UTF-8",
+        "LC_ALL": "en_US",
+        "NO_PROXY": "localhost",
+        "PATH": "/tmp/path",
+      },
+      "maxBuffer": 10485760,
+      "timeout": 900000,
+    },
+  },
+  Object {
+    "cmd": "dotnet restore project.csproj --force-evaluate --configfile others/nuget/not-so-random/nuget.config",
+    "options": Object {
+      "cwd": "/tmp/github/some/repo",
+      "encoding": "utf-8",
+      "env": Object {
+        "HOME": "/home/user",
+        "HTTPS_PROXY": "https://example.com",
+        "HTTP_PROXY": "http://example.com",
+        "LANG": "en_US.UTF-8",
+        "LC_ALL": "en_US",
+        "NO_PROXY": "localhost",
+        "PATH": "/tmp/path",
+      },
+      "maxBuffer": 10485760,
+      "timeout": 900000,
+    },
+  },
+]
+`;
+
 exports[`updateArtifacts supports docker mode 1`] = `
 Array [
   Object {
diff --git a/lib/manager/nuget/artifacts.spec.ts b/lib/manager/nuget/artifacts.spec.ts
index 549be8a5fdb909e1acb32dd84d3017d1bb40113a..1daf2149b6b6b931959e0cd0626ad86057a5617e 100644
--- a/lib/manager/nuget/artifacts.spec.ts
+++ b/lib/manager/nuget/artifacts.spec.ts
@@ -227,4 +227,26 @@ describe('updateArtifacts', () => {
     ).not.toBeNull();
     expect(execSnapshots).toMatchSnapshot();
   });
+  it('strips protocol version from feed url', async () => {
+    const execSnapshots = mockExecAll(exec);
+    fs.getSiblingFileName.mockReturnValueOnce('packages.lock.json');
+    fs.readLocalFile.mockResolvedValueOnce('Current packages.lock.json' as any);
+    fs.readLocalFile.mockResolvedValueOnce('New packages.lock.json' as any);
+    getConfiguredRegistries.mockResolvedValueOnce([
+      {
+        name: 'myRegistry',
+        url: 'https://my-registry.example.org#protocolVersion=3',
+      },
+    ] as never);
+    hostRules.find.mockImplementationOnce(() => ({}));
+    expect(
+      await nuget.updateArtifacts({
+        packageFileName: 'project.csproj',
+        updatedDeps: ['dep'],
+        newPackageFileContent: '{}',
+        config,
+      })
+    ).not.toBeNull();
+    expect(execSnapshots).toMatchSnapshot();
+  });
 });
diff --git a/lib/manager/nuget/artifacts.ts b/lib/manager/nuget/artifacts.ts
index 6795a2b48851bf9e2b2eb4cd61d3ecb493b441a5..9dbe7e6adaeab122e471425abc4fb2a6fc0e6860 100644
--- a/lib/manager/nuget/artifacts.ts
+++ b/lib/manager/nuget/artifacts.ts
@@ -1,6 +1,6 @@
 import { join } from 'path';
 import { TEMPORARY_ERROR } from '../../constants/error-messages';
-import { id } from '../../datasource/nuget';
+import { id, parseRegistryUrl } from '../../datasource/nuget';
 import { logger } from '../../logger';
 import { ExecOptions, exec } from '../../util/exec';
 import {
@@ -37,7 +37,8 @@ async function addSourceCmds(
       hostType: id,
       url: registry.url,
     });
-    let addSourceCmd = `dotnet nuget add source ${registry.url} --configfile ${nugetConfigFile}`;
+    const registryInfo = parseRegistryUrl(registry.url);
+    let addSourceCmd = `dotnet nuget add source ${registryInfo.feedUrl} --configfile ${nugetConfigFile}`;
     if (registry.name) {
       // Add name for registry, if known.
       addSourceCmd += ` --name ${registry.name}`;