LoadRunner and Performance Center
Showing results for 
Search instead for 
Do you mean 

Load testing of a REST API, using HP LoadRunner’s web_custom_request

Anonymous_User1 ‎08-20-2013 10:00 AM - edited ‎09-22-2015 01:38 PM

This post was written by Boris Kozorovitzky, from the LoadRunner R&D Team


In recent years, Representational State Transfer (REST) has become a dominant model for software architecture, especially for Web-based applications. Today, most large websites and Web applications on the Internet have REST APIs. Some examples of websites using REST APIs include Twitter, Google, Flickr and so on.


The great thing about a REST API is that it is usually well-defined and therefore allows clear separation between the client logic and the server logic. This property in itself is very beneficial for both functional and load testing of the application server. In the following article we will demonstrate an easy way to test your application’s REST API using HP LoadRunner’s web_custom_request method.


If you haven't experienced HP LoadRunner, here is your opportunity to download it.



Before we dive into load testing, let’s look at the basic terminology of a REST API. A REST API call consists of three major components:

  1. The Uniform Resource Identifier (URI) – This is a string which consists of three parts. The first part contains the host (and optionally, the port) of the API call (e.g. http://www.hp.com). The second part contains the path which identifies the call functionality. This path can include some parameter values although they are distinguishable from the constants only by semantics (e.g. /users/megwhitman/type/ceo, where “megwhitman” and “ceo” are parameters while “users” and “type” are constants). The third part is the QueryString which is a list of key-value pairs (e.g. user= megwhitman & type=ceo). The pairs are separated by the “&” sign and the entire QueryString is separated from the path by the “?” sign. A full URI may look something like this: http://www.shopping.hp.com/en_US/home-office/-/products/Tablets/Tablets?SearchParameter=ElitePad
  2. The verb – The verb can be any word describing the operation you want to perform on the URI. In HTTP, the five most commonly used verbs are: GET, POST, PUT, DELETE, and PATCH. Note that the operation for each verb is determined by the server although there are some common conventions in this area.
  3. The payload (data) – This is the data sent to the server with the request. For example, if we want to save a text file to the server, we can send the content of the text file as the payload.


Test Case

The example application under test is a todoMVC application which manages a ‘todo’ list.  This application has a REST API, as follows:

  • /todos, GET, No Payload – Retrieves all the todos currently in the list
  • /todos, POST, { isFinished :<isFinished>, todoText: <text>} – Creates a new todo on the server with the text provided in the payload by the <text> parameter.
  • /todos/<id>, PUT,  {id:<id>, todoText: <text>, isFinished:< isFinished>} – Updates the todo with id <id> with the text <text> and finished state < isFinished>

Note that all the data passed to and received from the server is in the JavaScript Object Notation (JSON) format which is gradually becoming the standard format for data transfer.


HP LoadRunner allows us to easily simulate HTTP calls through the web_custom_request function. We want to simulate a business process as follows:

1)      Get the existing todos from the server

2)      Add two new todos

3)      Update the last todo added with a new text


Step 1

We use recording to ‘learn’ this step. In VuGen we create a new Web - HTTP/HTML script and record a browser opening the todoMVC application. When the application starts, it gets all the todos currently stored on the server through the GET API call. We can easily find the correct step in the recorded script by looking at the URL argument. In this case the argument is - "URL=http://localhost:3000/todos" (since the application is running locally on port 3000 on my machine). The relevant step is:




The “Method” argument is the REST verb (GET in this case), and the “Snapshot” argument links to the correct snapshot file on the disk. The snapshot of this step can be viewed in the Snapshot Viewer:



We can see that the response from the server is a list of all the todos presented by our application in JSON format. 


Step 2

Adding a new todo is very simple. We create our own web_custom_request step with the parameters required by the POST  REST API. The created step looks something like this:


        web_custom_request("Add Todo"
        "Body={\"isFinished\":false,\"todoText\":\"This is VuGen\"}",


A few things to notice here:

1)      The “Method” (verb) is POST as required by the REST API.

2)      We specified the “EncType” parameter to inform the server that the payload is going to be in JSON format.

3)      We added our payload to the “Body” parameter in JSON format. 


Since writing the JSON in the middle of the script may be a bit cumbersome, we can add it as an extra file to the script. To do this simply right-click the “Extra Files” node in the Solution Explorer and select “Add Files to Script…”, and choose the data.json file we prepared earlier.  On a fresh installation of LoadRunner you may need to specify the .json extension as a valid extension for extra files. You can also do this after adding the file to your script. In VuGen, select Tools > Options > Scripting > Script Management and add the .json extension to the Allowed Extensions list. Once the file is added, the project looks something like this:



Now we can add the file as our payload by specifying the BodyFilePath parameter:


        web_custom_request("Add Todo from file"


Step 3

We want to update the last todo with some new values. To do this, we use another web_custom_request with the PUT verb as specified by the REST API. This is very similar to the step that adds a new todo:


    web_custom_request("Update Todo"
        "Body={\"id\":3, \"isFinished\":false,\"todoText\":\"Updated the name\"}",


This command updates the todo with id = 3 with the string “Updated the name”.

As with the previous step, you can manage the JSON text as a file, rather than writing it directly into the script.




We’ve seen how easy it is to create a simple load test with a REST API using HP LoadRunner.  The web_custom_request function is versatile enough to cover both simple and complex cases, thus simplifying REST API testing.



Leave us a comment in the box below to let us know how you’re using LoadRunner to load test your REST APIs.



Thanks to Boris for providing this article!


Click here to learn more about HP LoadRunner.

You can also download HP LoadRunner here.



About the Author


NaveenKumar N
on ‎08-21-2013 05:44 AM

Very insight article.

NaveenKumar N
on ‎08-21-2013 11:18 AM

How to install/host TODOMVC in my laptop? Please guide me. Thanks!

on ‎08-22-2013 12:15 AM



I will ask Malcolm to attach the implementation for the todoMVC application I talk about in the blog post.

To install it you need to have node.js installed. Once installed extract the attached zip file to some directory. I will refer to this directory as "c:\todoMVC" but you can extract to any directory.

Open the node.js command prompt (Start -> All Programs -> node.js -> node.js command prompt).

A cmd window will open. In the opened cmd window go to the directory where you extracted the zip file (e.g. "cd c:\todoMVC"). Type "npm install" (without the quotes) to download all the dependencies. If you are behind a proxy you will need to specify it using the --proxy flag (e.g. "npm install --proxy http://web-proxy.hst.hp.com:8080").

Run the application server by typing "node app.js". You should see the text: "Listening on port 3000" appear in the console.

Open your favorite browser (please don't use IE)  and type "localhost:3000" in the address bar. You should see the application running.

To reset the application go back to the cmd window and press Control+C to stop it, then type "node app.js" to start it. Note that closing the browser does not restart the application as it runs in the cmd window and the browser is used to access it.


Good Luck,




on ‎08-22-2013 12:24 AM

Thanks _Buzzy.  I've attached the file to the blog, as todo_mvc_example.zip

NaveenKumar N
on ‎08-23-2013 09:58 PM

I installed node.js and the I tried above steps. But I am not able to navigate to C:\todo_mvc_example  where I extracted the example. 



Please see this screenshot http://prntscr.com/1n2jrq


Could you please help me out? Thanks!

on ‎08-26-2013 12:02 AM

Hi NaveenKumar,


I think you ran "node.js" instead of the "node.js command prompt". 

Please follow the instructions I posted.




on ‎09-03-2013 02:55 PM

A timely article in my case.  I recently did this for an internal project.  I hadn't considered adding the body payload as a JSON file though and that may simplify things for some of my requests.

on ‎09-04-2013 12:19 AM

That's great news, SDMike.  Thanks for the feedback!

Bhaskar Venkataramana
on ‎10-23-2013 03:11 PM

but when we get the response if there is any "&" char than loadrunner will capture as "&amp", how do we resolve this issues

on ‎10-24-2013 04:53 AM



Could you please describe the problem in detail. I didn't understand what the issue is.

Bhaskar Venkataramana
on ‎10-24-2013 06:22 AM

can you help in Search and replace a character in a string


for eg:

web_reg_save_param("IDValues1","Notfound=warning" ,"LB=24skiptoken""RB=\"/></feed>""Ord=1","IgnoreRedirections=Yes"LAST);


the IDValues1 = "&amp%24skiptoken=hNhpItje6%2BpyE5PPcO9pOz0a%3B1000"


now i need to replace "&amp" with "&"

on ‎10-24-2013 06:56 AM



It is hard to help you since you are not giving any context of the problem and I don't understand what you are trying to do and how.


From the two lines you posted it seems that you need HTML decode the string and not search and replace.


Please ask scripting questions at our support forum here:





on ‎02-11-2014 02:13 PM

I tried this tecnique, but not geting a response on the POST. To validate that the GET is requesting and responding I'm looking in the Tree and then click on the HTTP view. I see a request and response. Very nice.

However when I try to validate a POST, I don't see a request or result in the Tree view. I tried putting a snapshot in the script, no results. Something else, the first time I ran this script today, I did get a result in the run-time viewer, but every run since then I never see a result. In the Replay log I see that the Action.c(38): web_custom_request("web_custom_request") was successful. But how do I know it was successful? I don't see a request or response. How do I know if the POST worked?

on ‎02-12-2014 12:56 AM

Hi Joe,


From your comment I understand you are using an older version of LR (11.0X). I tested my script with LR 11.52 although it should theoretically work with 11.0X.


You should see a response from the server in the snapshot RAW view. The response should be 200 OK.

If you don't see a snapshot at all, make sure you followed the steps correctly and that you have all the fields defined (especially Resource=0).


Hope this helps,


on ‎02-12-2014 09:24 AM

I'm doing something similar to step 1 and step 2 in the example. I see raw response data for step one or the first web_custom_request (the GET), but no raw data for step 2 (the POST).  I am using Resource=0, here is the code.

I'm also doing EncType=application/xstream instead of JSON, thanks for your help.




/*       "Snapshot=t2.inf",  */
           "<groupName>Hall Test*</groupName>"
    return 0;

on ‎02-13-2014 12:24 AM



It is hard to "debug" your script over a blog post comments. I don't see any problem with the script so there must be something specific to the application you are testing. Try to tweak it around some more and I am sure you will find the problem.


You can always open a support ticket and get one of our professional support people to help you with the script.




sandeep bansal
on ‎04-22-2014 05:38 PM

Hi Boris,


Thanks for excelent article. the most i liked is passing json using BodyFilePath. The question i have is how do we do parameterization if we specify it as file as we need to replace hard coded values with parameterized expression. do we specify it in json body file itself?

Raguraman B
on ‎04-30-2014 07:53 AM



My case is i dont have the front end UI & i am given a WADL for performance testing.


I have done scripting using WSDL but not used WADL in LR before. Is it possible to import the WADL similar to how we dit it for WSDL & test it ?


Please guide me.



on ‎05-20-2014 05:41 AM



Sorry for the late reply. I didn't get notifications on new comments until today :(


sandeep bansal: I don't know if your approach of adding the parameters in the file would work. You can try but I have a feeling you will have to put the content of the file in the script.


Raguraman: We don't currently support importing WADL out of the box but you can develop a VuGen extension to do it.





on ‎07-11-2014 05:46 AM

I want your help in getting perticuler param from json response in load runner.


for example in json response i am getting bellow response and i want to get value of id in parameter.



"content": "abcdefghijklmnopqrstuvwxyz",
"helpType": "FAQ",
"creationTimestamp": "Jul 11, 2014 1:13:18 PM",
"id": {
"id": "fd3d5111-6c2f-4bd9-acdf-36fade2ed79b"

Pavel Zaychik
on ‎09-17-2014 07:55 AM

Thanks for the article Boris. 

Can you help me out with adding basic authorization and more headers to the POST?

The POST request works fine from POSTMAN Chrome extension or from http://hurl.it and looks like that:


Accept: */*

Accept-Encoding: gzip, deflate

Authorization: Basic MTExMTExOjEyMzQ=

Cache-Control: no-cache

Content-Length: 27

Content-Type: application/json

Host: ec2-54-235-205-185.compute-1.amazonaws.com

Postman-Token: 4da3ad48-b5ed-da1d-e2b6-9dc6f13c37b9

User-Agent: runscope/0.1

BODY view raw
{"deviceId": "111111"}
I was not able to replicate it from Chrome Advance REST extension (can't figure out authorization setup) and can't figure out how to combine it with "web_set_user" Loadrunner function, which, when added in front of " web_custom_request" seams working. Basically, I think it comes to how to set up additional headers to the custom request.
Thanks in advance.
Pavel Zaychik
on ‎09-17-2014 08:29 AM

I finally figured out how to add headers and authorization. This is a working REST POST script:

    web_set_user("111111", "1234",
    web_add_header ("Host","ec2-54-235-205-185.compute-1.amazonaws.com:9080");
    web_add_header ("Authorization","Basic MTExMTExOjEyMzQ=");
        "Body={\"deviceId\" : \"111111\"}",
    return 0;

Awesome. Thanks Boris.

Also, many thanks to Vamsi Tokala and his blog at http://performancetestinginfo.blogspot.com/2010/05/testing-restful-web-services-using.html 

Pavel Zaychik
on ‎09-17-2014 01:09 PM

I'm trying to capture (for correlation purpose) the string returned by REST resonse body.

The script:

    web_set_user("111111", "1234",
    web_add_header ("Host","ec2-54-235-205-185.compute-1.amazonaws.com:9080");
    web_add_header ("Authorization","Basic MTExMTExOjEyMzQ=");
        "Body={\"deviceId\" : \"{deviceId}\"}",
    lr_output_message("Token value is: %s", lr_eval_string(TokenParm));
lr_end_transaction("Login", LR_AUTO);
    return 0;


The script works without lr_output_message. The compiler complains on unresolved parameter "TokenParm"...

Any suggestion would be appreciated.


on ‎09-18-2014 04:59 AM

Hi Pavel,


Incorrect line: lr_output_message("Token value is: %s", lr_eval_string(TokenParm));

Use: lr_output_message("Token value is: %s", lr_eval_string("{TokenParm}));

Note the quotes and { } characters.

I assume that you use { } as parameter delimiters in VuGen.


With kind regards,




on ‎09-18-2014 05:01 AM



lr_output_message("Token value is: %s", lr_eval_string("{TokenParm}"));


Forget an extra quote.





Pavel Zaychik
on ‎09-18-2014 07:22 AM

Thanks Dennis. This one works fine:

    lr_output_message("Token value is: %s", lr_eval_string("{TokenVal_1}"));

VuGen addes _1 when registering the parameter... Would you please elaborate on it? 

Thanks in advance.


on ‎09-25-2014 12:12 PM

Hi Pavel,


It is correct you have to use "TokenVal_1".

I did not look at your web_reg_save_param_ex options.


In your web_reg_save_param_ex you are using the option "Ordinal=all" .

It means that if there are more then one hits, with the specified boundaries, then all values are stored in an array.

Starting from value 1 to the number of values found e.g. TokenVal_1, TokenVal_2, TokenVal_3, etc.


If you remove the line "Ordinal=all" , you can use "TokenVal" instead of "TokenVal_1".


Got it?



Dineshkumar Chokkalingam
on ‎11-19-2014 10:45 PM



I am using the "bodyfilepath" method to call the .json file to run the web service request. Here as i need to run for load test, i am in need to parameterize the .json script. In LR i am allowed to do parameterize but getting error while running the script. If i run without the parameterization then the script runs sucessfully. Kindly find the below code for your reference.


Action script:



    return 0;


.Json Script;

    "method": "getCustomerAddress",
    "format": "application/json",
    "system": "amer",
    "companyId": "1234",
    "customerId": "{custid}" ,
    "addressCode": "{addrcode}"


Please help me in this regard. 

Thanks in Advance.

on ‎01-06-2015 06:32 AM

@Dineshkumar Chokkalingam,


I think the problem might be in the parameter delimiters that you are using within VuGen.

The '{' and '}' are your default parameter delimeters.

You can change the default delimiters in VuGen under the menu: Tools -> Options -> Tab Scripting -> Parameters.

Change 'Left parameter delimiter' and 'Right parameter delimiter' to another cahracter like '[' and ']'.

Re-record your script and give it a try.


I have no problem using the '{' and '}' with a custom request like:




This works fine for me.


With kind regards,



on ‎02-25-2015 02:20 AM
Hi I've tried using the bodypathfile option. I can see that the request is being sourced of this json file. The issue I am stuck with is, not being abLe to pass values to the parameters in the json file. I am yet to try modifying the delimiters but in the meanwhile if there is another solution, please share. Thank you.
on ‎02-15-2016 09:47 PM

hi,I notice that use NodeJs to be a server .

but I found Connect as a single module dont integration into Express4.x.

error log :

      throw new Error('Most middleware (like ' + name + ') is no longer bundled
with Express and must be installed separately. Please see https://github.com/sen

Error: Most middleware (like bodyParser) is no longer bundled with Express and m
ust be installed separately. Please see https://github.com/senchalabs/connect#mi
    at Function.Object.defineProperty.get (c:\mywork\code\todo_mvc_example\node_
    at Object.<anonymous> (c:\mywork\code\todo_mvc_example\app.js:6:16)
    at Module._compile (module.js:434:26)
    at Object.Module._extensions..js (module.js:452:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:475:10)
    at startup (node.js:118:18)
    at node.js:952:3

so you should intall it separately.

npm install connect

express4.x start up use this command 

npm start

then you can visit http://localhost:3000 successfully.


on ‎04-29-2016 02:16 AM


Is there any major difference in usering web_custom_request compared to web_rest?

I used web_rest in my script for API requests which worked perfectly.

All the information was written to an file to be provided to the devloper after the performance test.

Sriharsha Puranik
on ‎05-15-2016 06:04 AM



I need to use AWS Signature V4 authorization for a REST API POST request.  can anyone provide instructions on how to do it?

27 Feb - 2 March 2017
Barcelona | Fira Gran Via
Mobile World Congress 2017
Hewlett Packard Enterprise at Mobile World Congress 2017, Barcelona | Fira Gran Via Location: Hall 3, Booth 3E11
Read more
Each Month in 2017
Software Expert Days - 2017
Join us online to talk directly with our Software experts during online Expert Days. Find information here about past, current, and upcoming Expert Da...
Read more
View all