Why the endpoint text is still in the bytecode file
Hermes compiles the JavaScript bundle to bytecode before the app is packaged, so the file you extract is a binary program rather than source. Compilation removes structure and leaves data in place, and a compiled program still has to refer to its strings. Those strings live in a string table inside the file, where a URL path, a header name or a query parameter name usually sits as readable text.
That single fact sets the approach. Endpoint discovery on a Hermes bundle is a data extraction problem before it becomes a code reading problem, and the extraction is quick.
Confirm the format before reaching for a parser
Open the bundle in a JavaScript parser and it fails immediately, because the first bytes do not describe JavaScript. The file begins with a marker and a version field that belong to the bytecode format, and the version matters: a disassembler built for a different Hermes version will misread the tables.
- The marker identifies the file as Hermes bytecode. No formatter will turn it into a script, and a parser error on a file named as a bundle is the expected signal.
- The version field selects the tool. Read it first and match a disassembler to it, because the header layout and the instruction set change between versions.
- The header records where the tables sit. The string table, the function headers and the instruction stream are located by offsets, so a parser can walk them without disassembling anything.
Reading the string table in one pass
The fastest first result is a list of every string in the bundle. Extract them all and filter, rather than searching the file for a string you expect to find.
- Filter for transport shapes. A hostname, a leading slash, a query marker or a common REST word such as users, orders or search narrows thousands of entries to a shortlist.
- Filter for header and field names. Names such as authorization, content-type, or a parameter the capture showed you identify the function that builds a request.
- Expect fragments rather than full URLs. React Native code commonly concatenates a base URL with a path, so the base and the path appear as separate strings.
- Record the string index of each hit. The index links the data to the code, and the next step needs it.
Tying a string to the function that uses it
A string index is referenced from the instruction stream, so the disassembly can show which function loads a given string. Find the functions that reference your shortlist and read the instructions around those references. The pattern to look for is a call into the app's HTTP wrapper with a method, a path and an object of headers or fields. That wrapper is often one small module used by every call, and finding it once gives you the entry point for the rest.
A shared wrapper also scales the reading. When every request goes through one function, the arguments at each call site carry the endpoint, so collecting the call sites of that function produces the endpoint list and the surrounding fields together.
When the strings do not appear
Some builds transform the bundle after compilation. A build can encode parts of the string table, move strings into native modules, or deliver the bundle from a server so that the copy in the APK is only a bootstrap. The response is the same in each case: move to the running app and observe. A capture tells you what the endpoint is, and instrumentation of the running bundle tells you how the request was assembled.
From the list to a specification
The recovery is finished when each endpoint has a method, a path, its parameters, its authentication and the conditions the app applies before calling it. Verify each one against the server before writing it into documentation, because a path recovered from a string table can belong to a code path the app never reaches.
Deliverables are a Python, JavaScript or TypeScript client with an importable Postman collection and documentation, starting at $120, and most projects finish in 24 to 72 hours.
Related work
Reviewed 28 September 2026 · SReverse research desk