Request Construction and Replay
This article teaches you to modify a captured request and send it again, or to hand-craft a request from scratch and send it out: any captured request can be resent with one click, or edited and then resent; you can also assemble a brand-new request in the request builder. For private APIs with signatures / timestamps, use dynamic values to compute them on the fly and achieve a real replay; manage frequently used requests and multiple environments with collections / environments. Capturing traffic and calling APIs happen in the same place, so you don't have to switch tools back and forth.
1. When to Use It
Suitable if you meet any of the following:
- You captured a request and want to change a few parameters and send it again to see how the response changes.
- You want to hand-craft a request from scratch to call some API, filling in the method, URL, headers, and body yourself.
- The API carries a signature / timestamp / random number, and copying the old values verbatim won't work — you need to compute them fresh before each send.
- You need to switch back and forth among dev / test / production endpoints, or save frequently used requests for repeated use.
If what you want is to intercept traffic mid-flight and modify it manually, or to automatically rewrite traffic by rules, that's a different matter — see Rule Rewriting and Breakpoint Interception.
2. Prerequisites
- TraceEagle is installed and running.
- To "edit a captured request and resend it": first capture the target request (any capture method works; see Quick Start).
- To "hand-craft from scratch": know the API endpoint, method, and the required headers / body.
- For APIs with signatures, prepare the key / algorithm (e.g., the key used for HMAC, the field order used to build the signature).
3. Step-by-Step Operation
A. Resend a captured request with one click / edit it and send
- Right-click a request in the traffic list, or click "Edit and Resend" in the detail panel.
- The request is loaded into the request builder as-is: the URL is automatically restored from the protocol / host / port captured at capture time, the body and its type are auto-detected from the content, and irrelevant connection headers are automatically stripped — it opens ready to send.
- Change nothing and click Send for a one-click resend; to tweak parameters, edit the URL, parameter table, headers, or body, then click Send.
- Every send is recorded in a separate Composer session tab, retaining the full history, viewable, editable again, and comparable just like a captured request.
B. Hand-craft a request from scratch
Fill in each section in the request builder, then send:
- Request line: choose the method (GET / POST / PUT / DELETE / PATCH / HEAD / OPTIONS), enter the URL.
- Parameter table: query parameters are managed one per row, separately from the URL, and only joined together at send time — this way dynamic placeholders written in parameters won't be broken by premature encoding.
- Header table: one per row, add / remove / edit freely.
-
Auth helper: optionally None / Bearer Token / Basic (enter username + password, auto base64); it takes effect only when you haven't hand-written an
Authorizationheader. -
Request body: optionally none / JSON / form (form-urlencoded) / raw text; choosing JSON or form automatically adds the corresponding
Content-Type. - Click Send when done.
Don't want to fill it in cell by cell? You can directly paste a cURL command to import it as an editable request (supports common options such as
-X / -H / -d / --data-* / -u / -b / -A / -e; a request body automatically makes it POST); you can also import an external API collection file.
C. Use dynamic values for signatures / timestamps
For APIs with signatures, copying the old timestamp and signature won't go through. Write a ${...} dynamic value in any field, and it is computed on the fly into the real value before being sent:
| What you want | Write it like this |
|---|---|
| Random UUID |
${uuid} / ${randomUUID}
|
| Second-level timestamp | ${timestamp} |
| Millisecond-level timestamp |
${timestampMs} / ${now}
|
| 16-digit random hex | ${random} |
| Random integer in range | ${randomInt:min,max} |
| Base64 encode / decode |
${base64:} / ${base64url:} / ${base64decode:}
|
| Hash |
${md5:} / ${sha1:} / ${sha256:}
|
| HMAC signature |
${hmacSha256:key,msg} / ${hmacSha256Base64:key,msg} / ${hmacSha1:key,msg}
|
| URL encoding / case |
${urlEncode:} / ${upper:} / ${lower:}
|
-
Nesting works: for example
${hmacSha256:${secret},${body}}— first resolve the variables, then use them to compute the signature. - Common pattern: put
X-Timestamp: ${timestamp}in the headers andX-Sign: ${hmacSha256:${secret},${timestamp}}in the signature header, so the timestamp and signature update automatically on every send. - Anything that can't be computed is left as-is, so you can see at a glance which variable failed to resolve, instead of vaguely sending an empty value.
D. Manage things with collections / environments
-
Environment variables: extract
${name}into environment variables, configure dev / test / production sets, and switch the whole set of endpoints and parameters with one click; variables can also reference each other and expand in chains. - Collections: group frequently used requests into named groups; save the current request anytime and load it back anytime for reuse.
- Collections + environments are automatically saved as a plain-text file, which can be diffed and reviewed, making team sharing and traceability easy.
To make replay closer to the real path, you can enable, in the builder's Settings, sending with the same network characteristics as the capture session: go through an upstream proxy (http / socks5), restore the request fingerprint to a standard client, or specify a custom DNS resolution.
4. Verification: Confirm It Really Went Out and Came Back
- After clicking Send, the builder shows the status code, protocol, and elapsed time inline — receiving a response means the send went through.
- The send is recorded into the Composer session as a Flow; open it to see the full request and response, viewable and editable again just like a captured request.
- APIs with signatures: before sending, the dynamic values have already been computed locally into real values, so you can see exactly what is actually sent out; once the response is no longer "signature error / timestamp expired" but a normal business response, the replay succeeded.
- To confirm "what's different between this time and last time": put the replayed request side by side with the real captured request and compare line by line — see Request Diff.
5. Won't Send / Wrong Response? Troubleshoot Item by Item
| Symptom | Most likely cause | What to do |
|---|---|---|
| Response says "signature error / timestamp expired" | The signature field still holds the old value from capture time | Change it to a dynamic value computed on the fly, e.g. ${timestamp}, ${hmacSha256:key,msg}
|
A ${...} appears verbatim in the sent request |
The variable wasn't resolved (typo, or not defined in the environment) | Check the dynamic value spelling; if it's an environment variable, make sure it's defined in the current environment |
A ${...} in parameters turns into garbled text when sent |
The placeholder was encoded prematurely | Put query parameters in the parameter table and manage them row by row instead of stuffing them into the URL |
The sent body has no Content-Type
|
The body was set to none or raw text | Choose JSON or form to auto-add the corresponding Content-Type; or write one manually in the header table |
| Auth didn't take effect | You already hand-wrote the Authorization header |
The auth helper only takes effect when you haven't hand-written that header; pick one, don't duplicate |
| Switched environments but the address didn't change | The request hard-codes the address rather than using a variable | Extract the parts that change into ${name} environment variables, then switch environments |
| Replay works but results don't match the real path | Network characteristics differ from those at capture time | Align upstream proxy / request fingerprint / custom DNS in Settings |
6. Next Steps
- How to read captured requests, switch views, and decode: see Data Viewing and Decoding.
- To find out "what exactly differs between this replay and the last one": see Request Diff.
- To intercept mid-flight and modify manually, or rewrite automatically by rules: see Rule Rewriting and Breakpoint Interception.
- To export requests as cURL / Python / Go code and paste it into your project: see Code Generation and API Doc Export.
- To send one request repeatedly or in bulk under load: see Session Replay and Stress Testing.
Top comments (0)