diff --git a/license_sh/analyze/analyze_shared.py b/license_sh/analyze/analyze_shared.py
index ced7fb2..bb3be47 100644
--- a/license_sh/analyze/analyze_shared.py
+++ b/license_sh/analyze/analyze_shared.py
@@ -5,12 +5,11 @@ import subprocess
 from html.parser import HTMLParser
 from importlib import resources
 from sys import platform
-from typing import Dict, List
+from typing import Dict, List, Tuple
 
 from anytree import AnyNode, PreOrderIter
 
 from license_sh.analyze import lib
-from ..helpers import get_node_id
 
 IGNORED_HTML_TAGS = ["style", "script", "head"]
 GIT_IGNORE = ".gitignore"
@@ -83,7 +82,7 @@ def get_node_analyze_dict(directory: str) -> Dict:
     Returns:
         [Dict]: Project id as a key and Dict with license text and analyzed license name
     """
-    data_dict: Dict[str, List[Dict[str, str]]] = {}
+    data_dict: Dict[Tuple[str, str], List[Dict[str, str]]] = {}
     license_data = run_askalono(directory)
     for item in license_data:
         *path_to_dependency, license_file = item.get("path").split("/")
@@ -92,7 +91,7 @@ def get_node_analyze_dict(directory: str) -> Dict:
         if os.path.isfile(package_file_path):
             with open(package_file_path, "r") as package_file:
                 package_json = json.load(package_file)
-                node_id = get_node_id(
+                node_id = (
                     package_json.get("name", "project_name"),
                     package_json.get("version", "unknown"),
                 )
@@ -129,7 +128,7 @@ def add_analyze_to_dep_tree(analyze_dict: Dict, dep_tree: AnyNode):
         dep_tree (AnyNode): Dependency tree to update
     """
     for node in PreOrderIter(dep_tree):
-        node_analyze_list = analyze_dict.get(node.id)
+        node_analyze_list = analyze_dict.get((node.name, node.version))
         node.analyze = []
         if not node_analyze_list:
             continue
diff --git a/license_sh/analyze/maven.py b/license_sh/analyze/maven.py
index 6b55919..d63c944 100644
--- a/license_sh/analyze/maven.py
+++ b/license_sh/analyze/maven.py
@@ -4,7 +4,7 @@ import os
 import subprocess
 import tempfile
 import xml.etree.ElementTree as ET
-from typing import Dict, List
+from typing import Dict, List, Tuple
 from zipfile import ZipFile
 
 import aiohttp as aiohttp
@@ -15,7 +15,6 @@ from license_sh.analyze.analyze_shared import (
     add_analyze_to_dep_tree,
     transform_html,
 )
-from license_sh.helpers import get_node_id, decode_node_id
 
 
 def get_licenses_xml(directory: str):
@@ -53,10 +52,10 @@ def parse_licenses_xml(data_root) -> Dict:
     Returns:
         [Dict]: dependency id as key, licenses url list as value
     """
-    dep_data: Dict[str, List[str]] = {}
+    dep_data: Dict[Tuple[str, str], List[str]] = {}
 
     for dependency in data_root.find("dependencies"):
-        dep_id = get_node_id(
+        dep_id = (
             dependency.find("artifactId").text, dependency.find("version").text
         )
         licenses = dependency.find("licenses")
@@ -168,7 +167,7 @@ def merge_licenses_analysis_with_jar_analysis(
     for key, value in licenses_analysis.items():
         item = copy.deepcopy(value)
         result[key] = item
-        name, version = decode_node_id(key)
+        name, version = key
         jar_analyze_list = jar_analysis.get(f"{name}-{version}")
         if jar_analyze_list:
             item.extend(jar_analyze_list)
diff --git a/license_sh/commands/run_license_sh.py b/license_sh/commands/run_license_sh.py
index 0936003..6a3cb14 100644
--- a/license_sh/commands/run_license_sh.py
+++ b/license_sh/commands/run_license_sh.py
@@ -3,13 +3,13 @@ from typing import List
 
 import questionary
 
+from license_sh.version import __version__
 from license_sh.analyze import run_analyze
 from . import config_cmd
 from ..config import get_config, get_raw_config, whitelist_licenses, ignore_packages
 from ..helpers import (
     get_dependency_tree_with_licenses,
     get_problematic_packages_from_analyzed_tree,
-    label_dep_tree
 )
 from ..project_identifier import ProjectType, get_project_types
 from ..reporters.ConsoleReporter import ConsoleReporter
@@ -81,8 +81,9 @@ def run_license_sh(arguments):
 
     dep_tree: PackageNode = run_check(project_to_check, path, silent, debug)
 
-    # TODO we should deprecate this
-    label_dep_tree(dep_tree, project_to_check)
+    dep_tree.data_version = __version__
+    dep_tree.project = project_to_check.value
+
     ignored_packages = ignored_packages_map.get(project_to_check.value, [])
 
     if analyze:
diff --git a/license_sh/helpers.py b/license_sh/helpers.py
index abd5fc5..a95a8d6 100644
--- a/license_sh/helpers.py
+++ b/license_sh/helpers.py
@@ -8,7 +8,6 @@ from license_expression import Licensing, ExpressionError
 from license_sh.normalizer import normalize
 from license_sh.project_identifier import ProjectType
 from license_sh.types.nodes import PackageNode, PackageInfo, AnnotatedPackageNode
-from license_sh.version import __version__
 
 NODE_ID_SEP = ":-:"
 
@@ -249,23 +248,6 @@ def annotate_dep_tree(
     return tree, licenses_not_found
 
 
-def label_dep_tree(tree: PackageNode, project: ProjectType) -> PackageNode:
-    """
-    An idea of this function is to go through elements from the bottom -> up and
-    add parameters
-    :param tree
-    :param project type
-    :return tree
-    """
-    for node in PreOrderIter(tree):
-        node.project = project.value
-        node.id = get_node_id(node.name, node.version)
-        node.leaf = node.is_leaf
-        node.data_version = __version__
-
-    return tree
-
-
 def filter_dep_tree(tree: AnnotatedPackageNode) -> AnnotatedPackageNode:
     """Filter dependency tree.
 
@@ -315,22 +297,6 @@ def get_dependency_tree_with_licenses(
     return dependency_tree, unknown_licenses, has_issues
 
 
-def get_node_id(node_name: str, node_version: str) -> str:
-    """
-    Get node id from name and version
-    """
-    id_name = node_name.replace("/", ">")
-    id_version = node_version.replace("/", ">")
-    return f"{id_name}{NODE_ID_SEP}{id_version}"
-
-
-def decode_node_id(node_id: str) -> List:
-    """
-    Get name and version from node id
-    """
-    return node_id.split(NODE_ID_SEP)
-
-
 def is_problematic_node(node: AnyNode, check_subtree: bool = False) -> bool:
     """
     Determines whether there is an issue with a node.

Remove metadata
Remove metadata like `leaf`, ... . Deprecate label nodes
diff --git a/tests/analyze/test_analyze_shared.py b/tests/analyze/test_analyze_shared.py
index 29bab33..91517cb 100644
--- a/tests/analyze/test_analyze_shared.py
+++ b/tests/analyze/test_analyze_shared.py
@@ -8,9 +8,8 @@ from license_sh.analyze.analyze_shared import (
     add_analyze_to_dep_tree,
     run_askalono,
     get_node_analyze_dict,
-    transform_html,
+    transform_html
 )
-from license_sh.helpers import get_node_id
 
 ASKALONO_RESULT = [
     {
@@ -42,38 +41,42 @@ class Askalono_result:
 class AnalyzeSharedTestCase(unittest.TestCase):
     def test_add_analyze_to_dep_tree_simple(self):
         tree = AnyNode(
-            id="root",
+            name="root",
+            version="1.2.3",
             children=[
-                AnyNode(id="child", children=[AnyNode(id="childChild")]),
-                AnyNode(id="child2", children=[AnyNode(id="child2Child")]),
+                AnyNode(name="child", version="1.0.0", children=[AnyNode(name="childChild", version="1.0.0")]),
+                AnyNode(name="child2", version="1.0.1", children=[AnyNode(name="child2Child", version="9.9.9")]),
             ],
         )
+        root_id = ("root", "1.2.3")
+        childChild_Id = ("childChild", "1.0.0")
         analyze = {
-            "root": [{"data": "Hey! I am a license text", "name": "Awesome license"}],
-            "childChild": [
+            root_id: [{"data": "Hey! I am a license text", "name": "Awesome license"}],
+            childChild_Id: [
                 {"data": "Hmm, i am a license text too", "name": "Hmm license", }
             ],
         }
         updated_tree = add_analyze_to_dep_tree(analyze, tree)
         self.assertEqual(
-            updated_tree.analyze[0].get("data"), analyze.get("root")[0].get("data")
+            updated_tree.analyze[0].get("data"), analyze.get(root_id)[0].get("data")
         )
         self.assertEqual(
-            updated_tree.analyze[0].get("name"), analyze.get("root")[0].get("name")
+            updated_tree.analyze[0].get("name"), analyze.get(root_id)[0].get("name")
         )
         self.assertEqual(
             updated_tree.children[0].children[0].analyze[0].get("data"),
-            analyze.get("childChild")[0].get("data"),
+            analyze.get(childChild_Id)[0].get("data"),
         )
         self.assertEqual(
             updated_tree.children[0].children[0].analyze[0].get("name"),
-            analyze.get("childChild")[0].get("name"),
+            analyze.get(childChild_Id)[0].get("name"),
         )
 
     def test_add_analyze_to_dep_tree_license_file_negative(self):
-        tree = AnyNode(id="root")
+        tree = AnyNode(name="root", version="1.0.0")
+        root_id = ("root", "1.0.0")
         analyze = {
-            "root": [
+            root_id: [
                 {
                     "data": "Hey! I am a random text that might be license text",
                     "file": "README",
@@ -82,17 +85,18 @@ class AnalyzeSharedTestCase(unittest.TestCase):
         }
         updated_tree = add_analyze_to_dep_tree(analyze, tree)
         try:
-            self.assertEqual(updated_tree.license_text, analyze.get("root").get("data"))
+            self.assertEqual(updated_tree.license_text, analyze.get(root_id).get("data"))
             self.assertEqual(
-                updated_tree.license_analyzed, analyze.get("root").get("name")
+                updated_tree.license_analyzed, analyze.get(root_id).get("name")
             )
         except Exception:
             pass
 
     def test_add_analyze_to_dep_tree_license_file_positive(self):
-        tree = AnyNode(id="root")
+        tree = AnyNode(name="root", version="1.0.0")
+        root_id = ("root", "1.0.0")
         analyze = {
-            "root": [
+            root_id: [
                 {
                     "data": "Hey! I am a random text that might be license text",
                     "file": "LICENSE",
@@ -101,7 +105,7 @@ class AnalyzeSharedTestCase(unittest.TestCase):
         }
         updated_tree = add_analyze_to_dep_tree(analyze, tree)
         self.assertEqual(
-            updated_tree.analyze[0].get("data"), analyze.get("root")[0].get("data")
+            updated_tree.analyze[0].get("data"), analyze.get(root_id)[0].get("data")
         )
 
     @mock.patch("license_sh.analyze.analyze_shared.subprocess")
@@ -151,11 +155,11 @@ class AnalyzeSharedTestCase(unittest.TestCase):
         mock_json_load.return_value = {"name": project_name, "version": project_version}
         result = get_node_analyze_dict("shouldnt/matter")
         self.assertEqual(
-            result.get(get_node_id(project_name, project_version))[0].get("name"),
+            result.get((project_name, project_version))[0].get("name"),
             "Apache-2.0",
         )
         self.assertEqual(
-            result.get(get_node_id(project_name, project_version))[0].get("file"),
+            result.get((project_name, project_version))[0].get("file"),
             "LICENSE",
         )
 
@@ -181,7 +185,7 @@ class AnalyzeSharedTestCase(unittest.TestCase):
         mock_json_load.return_value = {"name": project_name, "version": project_version}
         result = get_node_analyze_dict("shouldnt/matter")
         self.assertEqual(
-            len(result.get(get_node_id(project_name, project_version))), 1,
+            len(result.get((project_name, project_version))), 1,
         )
 
     def test_transform_html_string(self):
diff --git a/tests/analyze/test_maven.py b/tests/analyze/test_maven.py
index 2bc7623..63e6097 100644
--- a/tests/analyze/test_maven.py
+++ b/tests/analyze/test_maven.py
@@ -14,7 +14,6 @@ from license_sh.analyze.maven import (
     analyze_maven,
     merge_licenses_analysis_with_jar_analysis,
 )
-from license_sh.helpers import get_node_id
 
 licenses_xml = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <licenseSummary>
@@ -83,11 +82,11 @@ class AnalyzeMavenTestCase(unittest.TestCase):
     def test_parse_licenses_xml(self):
         result = parse_licenses_xml(ET.fromstring(licenses_xml))
         self.assertEqual(
-            result.get(get_node_id("gson", "2.8.3")),
+            result.get(("gson", "2.8.3")),
             ["http://www.apache.org/licenses/LICENSE-2.0.txt"],
         )
         self.assertEqual(
-            result.get(get_node_id("javassist", "3.22.0-GA")),
+            result.get(("javassist", "3.22.0-GA")),
             [
                 "http://www.mozilla.org/MPL/MPL-1.1.html",
                 "http://www.gnu.org/licenses/lgpl-2.1.html",
@@ -109,8 +108,8 @@ class AnalyzeMavenTestCase(unittest.TestCase):
         self.assertEqual(result.get("redux-4.4.4-GA")[0].get("name"), "Apache-2.0")
 
     def test_merge_licenses_analysis_with_jar_analysis(self):
-        package1 = get_node_id("package_name", "package_version")
-        package2 = get_node_id("package_name2", "package_version2")
+        package1 = ("package_name", "package_version")
+        package2 = ("package_name2", "package_version2")
         licenses_analysis = {
             package1: [{"data": "License text", "name": "MIT", "file": "LICENSE.md"}],
             package2: [{"data": None, "name": None, "file": None}],
@@ -150,12 +149,13 @@ class AnalyzeMavenTestCase(unittest.TestCase):
         self, mock_get_maven_analyze_dict, mock_get_jar_analyze_data
     ):
         tree = AnyNode(
-            id=get_node_id("root", "1.0.0"),
+            name="root",
+            version="1.0.0",
             children=[
-                AnyNode(id=get_node_id("child", "0.0.2-GA")),
+                AnyNode(name="child", version="0.0.2-GA"),
                 AnyNode(
-                    id=get_node_id("child2", "0.0.5"),
-                    children=[AnyNode(id=get_node_id("childChild", "9.5.4"))],
+                    name="child2", version="0.0.5",
+                    children=[AnyNode(name="childChild", version="9.5.4")],
                 ),
             ],
         )
@@ -167,10 +167,10 @@ class AnalyzeMavenTestCase(unittest.TestCase):
             ],
         }
         mock_get_maven_analyze_dict.return_value = {
-            get_node_id("root", "1.0.0"): [{"data": "License text", "name": "MIT"}],
-            get_node_id("child", "0.0.2-GA"): [],
-            get_node_id("child2", "0.0.5"): [],
-            get_node_id("childChild", "9.5.4"): [
+            ("root", "1.0.0"): [{"data": "License text", "name": "MIT"}],
+            ("child", "0.0.2-GA"): [],
+            ("child2", "0.0.5"): [],
+            ("childChild", "9.5.4"): [
                 {"data": "License text", "name": "Apache-2.0"}
             ],
         }
@@ -189,6 +189,7 @@ class AnalyzeMavenTestCase(unittest.TestCase):
                 {"data": "MIT license", "name": "MIT"},
             ],
         )
+
         self.assertEqual(
             tree.children[1].children[0].analyze,
             [{"data": "License text", "name": "Apache-2.0"}],

pip install -e .[dev]
parse_log_pytest
pytest
pytest
3.9
Pipfile
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
aiohappyeyeballs==2.6.1
aiohttp==3.11.14
aiosignal==1.3.2
anytree==2.12.1
async-timeout==5.0.1
attrs==25.3.0
boolean.py==4.0
docopt==0.6.2
exceptiongroup @ file:///croot/exceptiongroup_1706031385326/work
frozenlist==1.5.0
idna==3.10
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
license-expression==30.4.1
-e git+https://github.com/webscopeio/license.sh.git@6688e183cbfad72fe9c50a6ef03b1de2cf568728#egg=license_sh
multidict==6.2.0
packaging @ file:///croot/packaging_1734472117206/work
pipdeptree==2.26.0
pluggy @ file:///croot/pluggy_1733169602837/work
prompt_toolkit==3.0.50
propcache==0.3.1
pytest @ file:///croot/pytest_1738938843180/work
questionary==2.1.0
six==1.17.0
termcolor==2.3.0
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work
typing_extensions==4.13.0
urllib3==2.3.0
wcwidth==0.2.13
yarl==1.18.3
yaspin==3.1.0

name: license.sh
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - exceptiongroup=1.2.0=py39h06a4308_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - packaging=24.2=py39h06a4308_0
  - pip=25.0=py39h06a4308_0
  - pluggy=1.5.0=py39h06a4308_0
  - pytest=8.3.4=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py39h06a4308_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - aiohappyeyeballs==2.6.1
      - aiohttp==3.11.14
      - aiosignal==1.3.2
      - anytree==2.12.1
      - async-timeout==5.0.1
      - attrs==25.3.0
      - boolean-py==4.0
      - docopt==0.6.2
      - frozenlist==1.5.0
      - idna==3.10
      - license-expression==30.4.1
      - multidict==6.2.0
      - pipdeptree==2.26.0
      - prompt-toolkit==3.0.50
      - propcache==0.3.1
      - questionary==2.1.0
      - six==1.17.0
      - termcolor==2.3.0
      - typing-extensions==4.13.0
      - urllib3==2.3.0
      - wcwidth==0.2.13
      - yarl==1.18.3
      - yaspin==3.1.0
prefix: /opt/conda/envs/license.sh

tests/analyze/test_analyze_shared.py::AnalyzeSharedTestCase::test_add_analyze_to_dep_tree_license_file_negative tests/analyze/test_analyze_shared.py::AnalyzeSharedTestCase::test_add_analyze_to_dep_tree_license_file_positive tests/analyze/test_analyze_shared.py::AnalyzeSharedTestCase::test_add_analyze_to_dep_tree_simple tests/analyze/test_analyze_shared.py::AnalyzeSharedTestCase::test_get_node_analyze_dict tests/analyze/test_analyze_shared.py::AnalyzeSharedTestCase::test_get_node_analyze_dict_duplicities tests/analyze/test_maven.py::AnalyzeMavenTestCase::test_analyze_maven tests/analyze/test_maven.py::AnalyzeMavenTestCase::test_merge_licenses_analysis_with_jar_analysis tests/analyze/test_maven.py::AnalyzeMavenTestCase::test_parse_licenses_xml
tests/analyze/test_analyze_shared.py::AnalyzeSharedTestCase::test_run_askalono_gitignore tests/analyze/test_analyze_shared.py::AnalyzeSharedTestCase::test_run_askalono_gitignore_error tests/analyze/test_analyze_shared.py::AnalyzeSharedTestCase::test_run_askalono_simple tests/analyze/test_analyze_shared.py::AnalyzeSharedTestCase::test_transform_html_complex tests/analyze/test_analyze_shared.py::AnalyzeSharedTestCase::test_transform_html_simple tests/analyze/test_analyze_shared.py::AnalyzeSharedTestCase::test_transform_html_string tests/analyze/test_analyze_shared.py::AnalyzeSharedTestCase::test_transform_html_xml tests/analyze/test_maven.py::AnalyzeMavenTestCase::test_call_copy_dependencies tests/analyze/test_maven.py::AnalyzeMavenTestCase::test_get_licenses_xml tests/analyze/test_maven.py::AnalyzeMavenTestCase::test_get_maven_analyze_dict tests/analyze/test_maven.py::AnalyzeMavenTestCase::test_jar_analyze_dict
license_sh/analyze/maven.py license_sh/analyze/analyze_shared.py license_sh/commands/run_license_sh.py license_sh/helpers.py
license_sh/analyze/maven.py license_sh/analyze/analyze_shared.py license_sh/commands/run_license_sh.py license_sh/helpers.py