How MAX_NODE_REPR_LENGTH Controls Chunk Count and Semantic Coherence in BetterHTMLChunking

The MAX_NODE_REPR_LENGTH parameter directly determines how DOM nodes are grouped into regions of interest, where smaller values increase chunk count and fragment semantic meaning, while larger values decrease chunk count but risk diluting coherence by merging unrelated sections.

In the carlosplanchon/betterhtmlchunking library, MAX_NODE_REPR_LENGTH serves as the primary tuning knob for balancing granularity against readability. This value dictates the maximum allowed length (in characters) for the HTML or text representation of a node before the chunking algorithm forces a boundary, fundamentally shaping how the final output aligns with the original document's logical structure.

What Is MAX_NODE_REPR_LENGTH?

MAX_NODE_REPR_LENGTH is an integer parameter passed to the DomRepresentation class in betterhtmlchunking/main.py. It defines the threshold at which the Tree Regions System decides to close the current region of interest (ROI) and begin a new one. The value is forwarded directly to the TreeRegionsSystem initialization at line 89-90, where it becomes max_node_repr_length for the internal ROIMaker instances.

How the Limit Drives Region Creation

The chunking pipeline follows a strict sequence governed by this single parameter:

  1. InitializationDomRepresentation passes MAX_NODE_REPR_LENGTH to TreeRegionsSystem (betterhtmlchunking/main.py#L89-L90).

  2. ROIMaker Setup – For each DOM node, the system instantiates a ROIMaker that stores the limit in its max_node_repr_length field (betterhtmlchunking/tree_regions_system.py#L68-L73).

  3. Length Calculation – The _process_children method walks child XPaths and queries get_node_repr_length to determine if the comparison uses raw text or full HTML length (betterhtmlchunking/tree_regions_system.py#L94-L100).

  4. Boundary Enforcement – If a single child exceeds the limit, the current region closes and the child is enqueued for deeper processing (betterhtmlchunking/tree_regions_system.py#L13-L21).

  5. Accumulation Check – When adding a child would push the accumulated length beyond the threshold, the algorithm finalizes the current region and starts a new one (betterhtmlchunking/tree_regions_system.py#L24-L31).

  6. Final Merge – After processing all children, any leftover region merges with the previous region to prevent tiny trailing fragments (betterhtmlchunking/tree_regions_system.py#L36-L44).

  7. Node-as-ROI Shortcut – If a node has no children or all children fit within one region, _check_node_as_roi promotes the entire node to a single ROI, preserving semantic unity (betterhtmlchunking/tree_regions_system.py#L46-L58).

Impact of Different MAX_NODE_REPR_LENGTH Values

Very Small Values (High Fragmentation)

Setting MAX_NODE_REPR_LENGTH to a small value (e.g., 10 characters) forces the algorithm to treat nearly every child as exceeding the limit. As demonstrated in tests/test_main.py#L77-L85 (test_small_max_node_repr_length), this produces many small chunks, often splitting single sentences or inline elements across boundaries. Semantic coherence suffers because related text fragments lose their contextual relationship.

Moderate Values (Balanced)

The default range of 100–200 characters (specifically 150 in the test suite) represents the optimal balance. Tests test_basic_initialization and test_full_pipeline at tests/test_main.py#L76-L84 show this generates a manageable number of chunks where each ROI typically contains complete paragraphs or logical sections. The _check_node_as_roi shortcut fires frequently enough to keep semantically related DOM subtrees intact without creating unwieldy mega-chunks.

Very Large Values (Low Granularity)

Increasing the limit to 10,000 characters or more (as in test_large_max_node_repr_length at tests/test_main.py#L91-L99) causes the algorithm to group almost all children into a single region. While chunk count drops dramatically, the resulting fragments may contain multiple unrelated sections (e.g., an entire article body including navigation, ads, and main content). This dilutes semantic coherence and complicates downstream tasks like summarization or embedding generation.

Edge Case: Exact Match

When a node's length equals MAX_NODE_REPR_LENGTH exactly, the logic at lines 13-21 of tree_regions_system.py treats it as a separate ROI. This ensures that large atomic elements—such as tables or code blocks that sit precisely at the limit—remain unsplit, preserving their structural integrity.

Code Example: Comparing Limits in Practice

from betterhtmlchunking.main import DomRepresentation
from betterhtmlchunking.tree_regions_system import ReprLengthComparisionBy

# Example HTML with nested structure

html = """
<html>
  <body>
    <section>
      <h1>Title</h1>
      <p>First paragraph with some text.</p>
      <p>Second paragraph with more text.</p>
    </section>
  </body>
</html>
"""

# 1. Small limit → many chunks, fragmented semantics

small = DomRepresentation(
    MAX_NODE_REPR_LENGTH=30,
    website_code=html,
    repr_length_compared_by=ReprLengthComparisionBy.HTML_LENGTH,
)
small.compute_tree_representation()
small.compute_tree_regions_system()
print(f"Small limit (30): {len(small.tree_regions_system.regions_of_interest_list)} chunks")

# Output: High chunk count, individual paragraphs may split

# 2. Moderate limit → balanced chunks

moderate = DomRepresentation(
    MAX_NODE_REPR_LENGTH=150,
    website_code=html,
    repr_length_compared_by=ReprLengthComparisionBy.HTML_LENGTH,
)
moderate.compute_tree_representation()
moderate.compute_tree_regions_system()
print(f"Moderate limit (150): {len(moderate.tree_regions_system.regions_of_interest_list)} chunks")

# Output: 2-3 chunks aligning with logical blocks

# 3. Large limit → few chunks, potential coherence dilution

large = DomRepresentation(
    MAX_NODE_REPR_LENGTH=10_000,
    website_code=html,
    repr_length_compared_by=ReprLengthComparisionBy.HTML_LENGTH,
)
large.compute_tree_representation()
large.compute_tree_regions_system()
print(f"Large limit (10000): {len(large.tree_regions_system.regions_of_interest_list)} chunks")

# Output: 1 chunk containing entire section

Summary

  • MAX_NODE_REPR_LENGTH is the central threshold that determines when the TreeRegionsSystem closes a region of interest and starts a new one.

  • Small values (e.g., 10-30 characters) generate many small chunks by forcing frequent boundaries, which fragments semantic units and breaks logical context across chunk boundaries.

  • Moderate values (default 100-200 characters) provide the optimal balance, keeping paragraphs and logical sections intact while maintaining manageable chunk sizes for downstream processing.

  • Large values (e.g., 10,000+ characters) produce few, oversized chunks that may merge unrelated sections, diluting semantic coherence and complicating tasks like summarization or embedding generation.

  • The algorithm includes safeguards such as the node-as-ROI shortcut (_check_node_as_roi) and final region merging to preserve atomic elements and prevent orphaned fragments regardless of the limit setting.

Frequently Asked Questions

What happens if I set MAX_NODE_REPR_LENGTH to a very small number like 10?

Setting the limit to 10 characters forces the ROIMaker to treat almost every child node as exceeding the threshold. According to the test test_small_max_node_repr_length in tests/test_main.py, this produces a high chunk count where single sentences or even inline HTML tags get split across separate regions, severely breaking semantic coherence.

Does a larger MAX_NODE_REPR_LENGTH always improve semantic coherence?

No. While larger values (e.g., 10,000 characters) keep more content together and reduce chunk count, they risk creating mega-chunks that combine unrelated sections like navigation menus, advertisements, and main article content. As shown in test_large_max_node_repr_length, this dilutes the semantic focus of each chunk and can degrade performance in downstream NLP tasks.

How does the library prevent tiny orphaned chunks at the end of documents?

The _process_children method in betterhtmlchunking/tree_regions_system.py includes a final merge step (lines 36-44) that combines any leftover region with the previous region after processing all children. This ensures that trailing content does not become a disproportionately small, semantically isolated chunk regardless of the MAX_NODE_REPR_LENGTH setting.

The test suite and default implementations suggest starting with 150 characters when using HTML length comparison, or a value between 100-200 for general use. This range allows the _check_node_as_roi shortcut to preserve logical DOM subtrees (like paragraphs and list items) while keeping chunks small enough for effective embedding and retrieval operations.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →