diff --git a/lib/platform/bitbucket/__snapshots__/index.spec.ts.snap b/lib/platform/bitbucket/__snapshots__/index.spec.ts.snap
index 5a3567ff52045f9d71fd439ffb2e31044c17d48c..3d6b461911c5e15b1a3341a2cf6e9f82e40abef9 100644
--- a/lib/platform/bitbucket/__snapshots__/index.spec.ts.snap
+++ b/lib/platform/bitbucket/__snapshots__/index.spec.ts.snap
@@ -912,7 +912,7 @@ Array [
 ]
 `;
 
-exports[`platform/bitbucket/index getJsonFile() ignores branchOrTag 1`] = `
+exports[`platform/bitbucket/index getJsonFile() returns file content 1`] = `
 Array [
   Object {
     "headers": Object {
@@ -938,7 +938,7 @@ Array [
 ]
 `;
 
-exports[`platform/bitbucket/index getJsonFile() returns file content 1`] = `
+exports[`platform/bitbucket/index getJsonFile() returns file content from branch or tag 1`] = `
 Array [
   Object {
     "headers": Object {
@@ -959,7 +959,44 @@ Array [
       "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)",
     },
     "method": "GET",
-    "url": "https://api.bitbucket.org/2.0/repositories/some/repo/src/HEAD/file.json",
+    "url": "https://api.bitbucket.org/2.0/repositories/some/repo/src/dev/file.json",
+  },
+]
+`;
+
+exports[`platform/bitbucket/index getJsonFile() returns file content from branch with a slash in its name 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "authorization": "Basic YWJjOjEyMw==",
+      "host": "api.bitbucket.org",
+      "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)",
+    },
+    "method": "GET",
+    "url": "https://api.bitbucket.org/2.0/repositories/some/repo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "authorization": "Basic YWJjOjEyMw==",
+      "host": "api.bitbucket.org",
+      "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)",
+    },
+    "method": "GET",
+    "url": "https://api.bitbucket.org/2.0/repositories/some/repo/refs/branches/feat/123-test",
+  },
+  Object {
+    "headers": Object {
+      "accept-encoding": "gzip, deflate, br",
+      "authorization": "Basic YWJjOjEyMw==",
+      "host": "api.bitbucket.org",
+      "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)",
+    },
+    "method": "GET",
+    "url": "https://api.bitbucket.org/2.0/repositories/some/repo/src/1234567890/file.json",
   },
 ]
 `;
diff --git a/lib/platform/bitbucket/index.spec.ts b/lib/platform/bitbucket/index.spec.ts
index 05cc557e711eeb516c77aea701005f396fb787c1..2027b0fdcc6be1a4df46977f6c35aa1f0ec5035b 100644
--- a/lib/platform/bitbucket/index.spec.ts
+++ b/lib/platform/bitbucket/index.spec.ts
@@ -966,17 +966,35 @@ describe('platform/bitbucket/index', () => {
       expect(httpMock.getTrace()).toMatchSnapshot();
     });
 
-    it('ignores branchOrTag', async () => {
+    it('returns file content from branch or tag', async () => {
       const data = { foo: 'bar' };
       const scope = await initRepoMock();
       scope
-        .get('/2.0/repositories/some/repo/src/HEAD/file.json')
+        .get('/2.0/repositories/some/repo/src/dev/file.json')
         .reply(200, JSON.stringify(data));
       const res = await bitbucket.getJsonFile('file.json', 'some/repo', 'dev');
       expect(res).toEqual(data);
       expect(httpMock.getTrace()).toMatchSnapshot();
     });
 
+    it('returns file content from branch with a slash in its name', async () => {
+      const data = { foo: 'bar' };
+      const scope = await initRepoMock();
+      scope
+        .get('/2.0/repositories/some/repo/refs/branches/feat/123-test')
+        .reply(200, JSON.stringify({ target: { hash: '1234567890' } }));
+      scope
+        .get('/2.0/repositories/some/repo/src/1234567890/file.json')
+        .reply(200, JSON.stringify(data));
+      const res = await bitbucket.getJsonFile(
+        'file.json',
+        'some/repo',
+        'feat/123-test'
+      );
+      expect(res).toEqual(data);
+      expect(httpMock.getTrace()).toMatchSnapshot();
+    });
+
     it('throws on malformed JSON', async () => {
       const scope = await initRepoMock();
       scope
diff --git a/lib/platform/bitbucket/index.ts b/lib/platform/bitbucket/index.ts
index 31b36a17ff5d94390e8a0d9f11f0a5bc5b276871..1b9803120d8c79b4a6c1e4da6e4c9dbc8b37861d 100644
--- a/lib/platform/bitbucket/index.ts
+++ b/lib/platform/bitbucket/index.ts
@@ -48,6 +48,8 @@ let config: utils.Config = {} as any;
 
 const defaults = { endpoint: BITBUCKET_PROD_ENDPOINT };
 
+const pathSeparator = '/';
+
 let renovateUserUuid: string;
 
 export async function initPlatform({
@@ -116,7 +118,17 @@ export async function getRawFile(
   // See: https://developer.atlassian.com/bitbucket/api/2/reference/resource/repositories/%7Bworkspace%7D/%7Brepo_slug%7D/src/%7Bcommit%7D/%7Bpath%7D
   const repo = repoName ?? config.repository;
   const path = fileName;
-  const url = `/2.0/repositories/${repo}/src/HEAD/${path}`;
+
+  let finalBranchOrTag = branchOrTag;
+  if (branchOrTag?.includes(pathSeparator)) {
+    // Branch name contans slash, so we have to replace branch name with SHA1 of the head commit; otherwise the API will not work.
+    finalBranchOrTag = await getBranchCommit(branchOrTag);
+  }
+
+  const url =
+    `/2.0/repositories/${repo}/src/` +
+    (finalBranchOrTag || `HEAD`) +
+    `/${path}`;
   const res = await bitbucketHttp.get(url);
   return res.body;
 }