diff --git a/base/BUILD.gn b/base/BUILD.gn
index a3adebbb86732..80817eb788098 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -2374,6 +2374,8 @@ component("base") {
       "trace_event/memory_usage_estimator.cc",
       "trace_event/memory_usage_estimator.h",
       "trace_event/optional_trace_event.h",
+      "trace_event/perfetto_proto_appender.cc",
+      "trace_event/perfetto_proto_appender.h",
       "trace_event/process_memory_dump.cc",
       "trace_event/process_memory_dump.h",
       "trace_event/trace_arguments.cc",
diff --git a/base/trace_event/perfetto_proto_appender.cc b/base/trace_event/perfetto_proto_appender.cc
new file mode 100644
index 0000000000000..31b4b53450681
--- /dev/null
+++ b/base/trace_event/perfetto_proto_appender.cc
@@ -0,0 +1,32 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/trace_event/perfetto_proto_appender.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <vector>
+
+#include "third_party/perfetto/include/perfetto/protozero/contiguous_memory_range.h"
+#include "third_party/perfetto/protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
+
+namespace base::trace_event {
+
+PerfettoProtoAppender::PerfettoProtoAppender(
+    perfetto::protos::pbzero::DebugAnnotation* proto)
+    : annotation_proto_(proto) {}
+
+PerfettoProtoAppender::~PerfettoProtoAppender() = default;
+
+void PerfettoProtoAppender::AddBuffer(uint8_t* begin, uint8_t* end) {
+  ranges_.push_back({.begin = begin, .end = end});
+}
+
+size_t PerfettoProtoAppender::Finalize(uint32_t field_id) {
+  return annotation_proto_->AppendScatteredBytes(field_id, ranges_.data(),
+                                                 ranges_.size());
+}
+
+}  // namespace base::trace_event
diff --git a/base/trace_event/perfetto_proto_appender.h b/base/trace_event/perfetto_proto_appender.h
new file mode 100644
index 0000000000000..2436a4bb814cd
--- /dev/null
+++ b/base/trace_event/perfetto_proto_appender.h
@@ -0,0 +1,35 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_TRACE_EVENT_PERFETTO_PROTO_APPENDER_H_
+#define BASE_TRACE_EVENT_PERFETTO_PROTO_APPENDER_H_
+
+#include <vector>
+
+#include "base/memory/raw_ptr.h"
+#include "base/trace_event/trace_arguments.h"
+#include "third_party/perfetto/include/perfetto/protozero/contiguous_memory_range.h"
+#include "third_party/perfetto/protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
+
+namespace base::trace_event {
+
+class BASE_EXPORT PerfettoProtoAppender
+    : public ConvertableToTraceFormat::ProtoAppender {
+ public:
+  explicit PerfettoProtoAppender(
+      perfetto::protos::pbzero::DebugAnnotation* proto);
+  ~PerfettoProtoAppender() override;
+
+  // ConvertableToTraceFormat::ProtoAppender:
+  void AddBuffer(uint8_t* begin, uint8_t* end) override;
+  size_t Finalize(uint32_t field_id) override;
+
+ private:
+  std::vector<protozero::ContiguousMemoryRange> ranges_;
+  raw_ptr<perfetto::protos::pbzero::DebugAnnotation> annotation_proto_;
+};
+
+}  // namespace base::trace_event
+
+#endif  // BASE_TRACE_EVENT_PERFETTO_PROTO_APPENDER_H_
diff --git a/base/trace_event/trace_arguments.cc b/base/trace_event/trace_arguments.cc
index 1f6f57189ab7e..63f336cbec6a1 100644
--- a/base/trace_event/trace_arguments.cc
+++ b/base/trace_event/trace_arguments.cc
@@ -26,6 +26,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/trace_event/perfetto_proto_appender.h"
 
 namespace base {
 namespace trace_event {
@@ -120,29 +121,6 @@ void AppendValueDebugString(const TraceArguments& args,
   *out += ")";
 }
 
-class PerfettoProtoAppender : public ConvertableToTraceFormat::ProtoAppender {
- public:
-  explicit PerfettoProtoAppender(
-      perfetto::protos::pbzero::DebugAnnotation* proto)
-      : annotation_proto_(proto) {}
-  ~PerfettoProtoAppender() override = default;
-
-  void AddBuffer(uint8_t* begin, uint8_t* end) override {
-    ranges_.emplace_back();
-    ranges_.back().begin = begin;
-    ranges_.back().end = end;
-  }
-
-  size_t Finalize(uint32_t field_id) override {
-    return annotation_proto_->AppendScatteredBytes(field_id, ranges_.data(),
-                                                   ranges_.size());
-  }
-
- private:
-  std::vector<protozero::ContiguousMemoryRange> ranges_;
-  raw_ptr<perfetto::protos::pbzero::DebugAnnotation> annotation_proto_;
-};
-
 }  // namespace
 
 void StringStorage::Reset(size_t alloc_size) {
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc
index 21fc12305468d..43204b1f0172c 100644
--- a/base/trace_event/trace_log.cc
+++ b/base/trace_event/trace_log.cc
@@ -39,6 +39,7 @@
 #include "base/task/single_thread_task_runner.h"
 #include "base/threading/platform_thread.h"
 #include "base/time/time.h"
+#include "base/trace_event/perfetto_proto_appender.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
 #include "third_party/perfetto/include/perfetto/ext/trace_processor/export_json.h"  // nogncheck
@@ -94,31 +95,6 @@ void InitializeMetadataEvent(TraceEvent* trace_event,
       &args, TRACE_EVENT_FLAG_NONE);
 }
 
-class PerfettoProtoAppender
-    : public base::trace_event::ConvertableToTraceFormat::ProtoAppender {
- public:
-  explicit PerfettoProtoAppender(
-      perfetto::protos::pbzero::DebugAnnotation* proto)
-      : annotation_proto_(proto) {}
-  ~PerfettoProtoAppender() override = default;
-
-  // ProtoAppender implementation
-  void AddBuffer(uint8_t* begin, uint8_t* end) override {
-    ranges_.emplace_back();
-    ranges_.back().begin = begin;
-    ranges_.back().end = end;
-  }
-
-  size_t Finalize(uint32_t field_id) override {
-    return annotation_proto_->AppendScatteredBytes(field_id, ranges_.data(),
-                                                   ranges_.size());
-  }
-
- private:
-  std::vector<protozero::ContiguousMemoryRange> ranges_;
-  raw_ptr<perfetto::protos::pbzero::DebugAnnotation> annotation_proto_;
-};
-
 void AddConvertableToTraceFormat(
     base::trace_event::ConvertableToTraceFormat* value,
     perfetto::protos::pbzero::DebugAnnotation* annotation) {
diff --git a/services/tracing/public/cpp/perfetto/traced_value_proto_writer.cc b/services/tracing/public/cpp/perfetto/traced_value_proto_writer.cc
index c013a42b97f2e..d35b16801dc12 100644
--- a/services/tracing/public/cpp/perfetto/traced_value_proto_writer.cc
+++ b/services/tracing/public/cpp/perfetto/traced_value_proto_writer.cc
@@ -28,22 +28,6 @@ using TraceEvent = base::trace_event::TraceEvent;
 
 namespace tracing {
 
-PerfettoProtoAppender::PerfettoProtoAppender(DebugAnnotation* proto)
-    : annotation_proto_(proto) {}
-
-PerfettoProtoAppender::~PerfettoProtoAppender() = default;
-
-void PerfettoProtoAppender::AddBuffer(uint8_t* begin, uint8_t* end) {
-  ranges_.emplace_back();
-  ranges_.back().begin = begin;
-  ranges_.back().end = end;
-}
-
-size_t PerfettoProtoAppender::Finalize(uint32_t field_id) {
-  return annotation_proto_->AppendScatteredBytes(field_id, ranges_.data(),
-                                                 ranges_.size());
-}
-
 namespace {
 
 constexpr size_t kDefaultSliceSize = 128;
diff --git a/services/tracing/public/cpp/perfetto/traced_value_proto_writer.h b/services/tracing/public/cpp/perfetto/traced_value_proto_writer.h
index 5ecc0dcca4b06..a81760c330222 100644
--- a/services/tracing/public/cpp/perfetto/traced_value_proto_writer.h
+++ b/services/tracing/public/cpp/perfetto/traced_value_proto_writer.h
@@ -6,36 +6,9 @@
 #define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_TRACED_VALUE_PROTO_WRITER_H_
 
 #include "base/component_export.h"
-#include "base/memory/raw_ptr.h"
-#include "base/trace_event/trace_event_impl.h"
-#include "third_party/perfetto/include/perfetto/protozero/contiguous_memory_range.h"
-
-namespace perfetto {
-namespace protos {
-namespace pbzero {
-class DebugAnnotation;
-}  // namespace pbzero
-}  // namespace protos
-}  // namespace perfetto
 
 namespace tracing {
 
-class COMPONENT_EXPORT(TRACING_CPP) PerfettoProtoAppender
-    : public base::trace_event::ConvertableToTraceFormat::ProtoAppender {
- public:
-  explicit PerfettoProtoAppender(
-      perfetto::protos::pbzero::DebugAnnotation* proto);
-  ~PerfettoProtoAppender() override;
-
-  // ProtoAppender implementation
-  void AddBuffer(uint8_t* begin, uint8_t* end) override;
-  size_t Finalize(uint32_t field_id) override;
-
- private:
-  std::vector<protozero::ContiguousMemoryRange> ranges_;
-  raw_ptr<perfetto::protos::pbzero::DebugAnnotation> annotation_proto_;
-};
-
 void COMPONENT_EXPORT(TRACING_CPP) RegisterTracedValueProtoWriter();
 
 }  // namespace tracing
diff --git a/services/tracing/public/cpp/perfetto/traced_value_proto_writer_unittest.cc b/services/tracing/public/cpp/perfetto/traced_value_proto_writer_unittest.cc
index 21e68f5a2620d..25f48f81bc0d8 100644
--- a/services/tracing/public/cpp/perfetto/traced_value_proto_writer_unittest.cc
+++ b/services/tracing/public/cpp/perfetto/traced_value_proto_writer_unittest.cc
@@ -13,6 +13,8 @@
 #include <string>
 
 #include "base/memory/raw_ptr.h"
+#include "base/notreached.h"
+#include "base/trace_event/perfetto_proto_appender.h"
 #include "base/trace_event/traced_value.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/perfetto/include/perfetto/protozero/scattered_heap_buffer.h"
@@ -107,7 +109,7 @@ bool IsValue(const NestedValue* proto_value, const char* value) {
 
 NestedValue GetProtoFromTracedValue(TracedValue* traced_value) {
   protozero::HeapBuffered<perfetto::protos::pbzero::DebugAnnotation> proto;
-  PerfettoProtoAppender proto_appender(proto.get());
+  base::trace_event::PerfettoProtoAppender proto_appender(proto.get());
   EXPECT_TRUE(traced_value->AppendToProto(&proto_appender));
 
   DebugAnnotation full_proto;