String#bytesize
str.bytesize -> integer String#bytesize returns the number of bytes in a string when encoded. This differs from length because multi-byte characters, like UTF-8 encoded non-ASCII characters, use more than one byte per character.
That difference matters whenever the code talks to storage, APIs, or other systems that care about byte limits instead of visible characters. The method gives you the encoded size directly, which makes it easier to compare the text against an external constraint.
Syntax
string.bytesize
Parameters
This method takes no parameters.
The examples below start with an ASCII baseline, then move into multibyte text so the contrast is easy to see. That order helps when you are explaining byte limits to someone who already knows the visible text length.
Examples
Basic ASCII usage
hello = "Hello"
hello.bytesize
# => 5
This is the simplest case because the visible character count and the byte count stay the same. It gives you a clean starting point before the multibyte examples introduce any extra complexity.
It also gives you a baseline for the later comparisons. Once the counts diverge, it is much easier to point back to this simple case and show what changed.
UTF-8 characters
greeting = "こんにちは"
greeting.length
# => 5
greeting.bytesize
# => 15 (each character is 3 bytes in UTF-8)
This is the core distinction the method is meant to expose. A value can look short and still occupy more bytes than you expect, so bytesize is the safer check whenever a limit is based on storage or transfer size.
The multibyte case is the one that tends to surprise people most, because the text still reads naturally even though the byte count jumps. That is exactly why the method is so useful in validation code.
Mixed content
ascii = "ruby"
ascii.length # => 4
ascii.bytesize # => 4
utf8 = "rüby"
utf8.length # => 4
utf8.bytesize # => 5 (ü = 2 bytes in UTF-8)
emoji = "🎉"
emoji.length # => 1
emoji.bytesize # => 4 (emoji are 4 bytes in UTF-8)
Mixed values are the easiest place to misread a limit because the counts do not move together. When a field combines ASCII and multibyte characters, bytesize tells you the real size that a database column or API will see.
This makes the method a practical debugging tool as well as a validation check. If two inputs have the same visible length but behave differently, byte size is usually the missing piece.
Compare characters and bytes
sample = "rüby"
sample.length
# => 4
sample.bytesize
# => 5
Seeing both values side by side makes the trade-off concrete. The visible text looks almost the same as "ruby", but the encoded form is a little larger, which is exactly why byte-based checks matter.
That side-by-side comparison is also a good way to explain the difference to other developers. Once the two counts are in front of you, the reason for the validation rule becomes obvious.
Common Patterns
Check string encoding size for storage
def fits_in_column?(text, max_bytes)
text.bytesize <= max_bytes
end
fits_in_column?("Hello", 255)
# => true
fits_in_column?("こんにちは", 255)
# => true (15 bytes)
fits_in_column?("a" * 300, 255)
# => false
This kind of helper is common when an application stores text in a database column with a fixed byte limit. It keeps the byte rule in one place instead of scattering the same comparison through the codebase.
The helper also makes the contract explicit for anyone reading the method name. A caller can tell immediately that the check is about storage size, not visible character count.
Calculate string memory usage
text = "Hello World"
memory_bytes = text.bytesize + 8 # +8 for string object overhead estimate
# => 19
This estimate is rough, but it can still be useful when you only need to know whether a string is in the right size range. For exact memory profiling, you would use a different tool, but bytesize still gives the text-specific part of the calculation.
The rough estimate is enough for quick checks and design discussions. If you only need to know whether a payload is getting too large, that byte count is usually the first number to reach for.
For more exact memory analysis, you would reach for a profiler or a dedicated inspection tool. The point here is just to show how bytesize can give you a useful size signal without extra machinery.
Handle encoding in API calls
# Many APIs have byte limits, not character limits
def within_byte_limit?(text, limit)
text.bytesize <= limit
end
That guard keeps the policy at the boundary instead of scattering byte checks through the app. If the API changes its limit later, you only need to update the guard instead of every call site.
That boundary check also makes the failure mode easier to explain. A caller can see the exact limit in one place, which is much clearer than guessing where the text was rejected.
That clarity is helpful when the limit is enforced by another service. The code can show the rule once and then stay focused on the request flow instead of re-describing the size constraint.
Validate against a byte budget
PAYLOAD_LIMIT_BYTES = 1024
def payload_ok?(text)
text.bytesize <= PAYLOAD_LIMIT_BYTES
end
payload_ok?("Hello") # => true
payload_ok?("🎉" * 300) # => false (1200 bytes)
A byte budget is common in messaging, logging, and network protocols where the payload size matters more than the visible length. Checking with bytesize keeps the validation fast and the rule obvious to anyone reading the code.
Performance Notes
bytesize runs in O(1) constant time because the byte count is cached in the string object.
Errors
This method never raises an error. It works on any string object and returns an integer, even for empty strings:
"".bytesize
# => 0
thinking in bytes instead of characters
bytesize matters whenever the program is talking to a system that cares about storage or wire size instead of character count. That includes database columns, file formats, and APIs with byte limits. The method keeps the check simple: it answers how much space the encoded string uses, not how many visible symbols the text appears to contain. That distinction is important for international text, where a short-looking string may still take more space than expected.
For that reason, bytesize is often a better guard than length when the code is dealing with external limits. It gives the caller a direct way to compare the string against a byte budget and decide whether to trim, reject, or transform the value before it goes any further.
That directness is especially handy in code that stores text or sends it over the wire, because the check stays close to the actual limit being enforced. The method does not try to interpret the text for you; it simply measures the encoded size. That keeps the rule obvious and helps avoid surprises when multibyte text is involved.
If you need to compare the same string in several forms, it often helps to calculate length and bytesize together and keep both numbers in the code for a moment. That makes it easier to explain why a value passed one check but failed another.