Adding CORS support to an API proxy Stay organized with collections Save and categorize content based on your preferences.
This pageapplies toApigee andApigee hybrid.
View Apigee Edge documentation.![]()
CORS (Cross-origin resource sharing) is a standard mechanism that allows JavaScript XMLHttpRequest (XHR) calls executed in a web page to interact with resources from non-origin domains. CORS is a commonly implemented solution to thesame-origin policy that is enforced by all browsers. For example, if you make an XHR call to the Twitter API from JavaScript code executing in your browser, the call will fail. This is because the domain serving the page to your browser is not the same as the domain serving the Twitter API. CORS provides a solution to this problem by allowing servers toopt-in if they wish to provide cross-origin resource sharing.
Note: Most modern browsers support CORS. SeeCross-Origin Resource Sharing to view a comprehensive list of supported browsers. For an in-depth description of CORS, see theFetch Living Standard.If you are using acache policy on your API proxy, you must ensure that the response of the CORS policy is not cached.
Typical use case for CORS
The following JQuery code calls a fictitious target service. If executed from within the context of a browser (a web page), the call will fail because of the same-origin policy:
<script>varurl="http://service.example.com";$(document).ready(function(){$("button").click(function(){$.ajax({type:"GET",url:url,async:true,dataType:"json",success:function(json){//Parsetheresponse.//Dootherthings.},error:function(xhr,status,err){//Thisiswhereweendup!}});});});</script>
One solution to this problem is to create an Apigee API proxy that calls the service API on the back end. Remember that Apigee sits between the client (a browser in this case) and the backend API (the service). Because the API proxy executes on the server, not in a browser, itis able to call the service successfully. Then, all you need to do is attach CORS headers to the TargetEndpoint response. As long as the browser supports CORS, these headers signal to the browser that it's okay torelax its same-origin policy, allowing the cross-origin API call to succeed.
Once the proxy with CORS support is created, you can call the API proxy URL instead of the backend service in your client-side code. For example:
<script>varurl="http://myorg-test.apigee.net/v1/example";$(document).ready(function(){$("button").click(function(){$.ajax({type:"GET",url:url,async:true,dataType:"json",success:function(json){//Parsetheresponse.//Dootherthings.},error:function(xhr,status,err){//Thistime,wedonotenduphere!}});});});</script>
Attaching the CORS policy to the request PreFlow of the ProxyEndpoint
Attaching an Add CORS policy to a new API proxy
You can add CORS support to an API proxy by attaching anAdd CORS policy to the API proxy in the following ways:
- When you create the policy by selecting theAdd CORS headers checkbox in theSecurity page of theBuild a Proxy wizard
- Byadding it later from theAdd Policy dialog
When you add the CORS policy by selecting the checkbox, a policy calledAdd CORS is automatically added to the system and attached to theTargetEndpoint request preflow.
TheAdd CORS policy adds the appropriate headers to the response. Basically, the headers let the browser know which origins it will share its resources with, which methods it accepts, and so on. You can read more about these CORS headers in theCross-Origin Resource Sharing W3C Recommendation.
You should modify the policy, as follows:
- Add the
content-typeandauthorizationheaders (required to support basic authentication or OAuth2) to theAccess-Control-Allow-Headersheader, as shown in the code excerpt below. - For OAuth2 authentication, you may need to take steps to correct non-RFC-compliant behavior.
<CORScontinueOnError="false"enabled="true"name="add-cors"><DisplayName>AddCORS</DisplayName><AllowOrigins>{request.header.origin}</AllowOrigins><AllowMethods>GET,PUT,POST,DELETE</AllowMethods><AllowHeaders>origin,x-requested-with,accept,content-type,authorization</AllowHeaders><ExposeHeaders>*</ExposeHeaders><MaxAge>3628800</MaxAge><AllowCredentials>false</AllowCredentials><GeneratePreflightResponse>true</GeneratePreflightResponse><IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables></CORS>
Adding CORS headers to an existing proxy
Apigee in Cloud console
To add the CORS policy to an existing API proxy:
In the Google Cloud console, go to theProxy Development> API Proxies page.
- Select the API proxy to which you want to add the CORS policy. The UI displays the proxy details in the Google Cloud console.
- Click theDevelop tab.
- In the navigation pane, click the+ button in thePolicies row.
In theCreate policy dialog, click theSelect policy field and scroll down toSecurity and selectCORS.
Enter the details for the policy and clickCreate.
- In the navigation pane, clickPreFlow underTarget Endpoints > default.
- Click the+ button next toPreFlow in theRequest pane of the Visual Editor.
- In theAdd policy step dialog, select theCORS policy.
ClickAdd to attach the policy.
Classic UI
To add the CORS policy to an existing API proxy:
- Sign in to theApigee UI.
- SelectDevelop > API Proxies in the left navigation bar. If you see theTry now button, click it to display the newDevelop view.
- Select the API proxy which you want to add the CORS policy.
- In the editor for the new API proxy, click theDevelop tab:
- In the left Navigator pane, clickPreFlow underTarget Endpoints > default.
- Click the top+Step button, corresponding to the Request PreFlow. This displays a categorized list of all the policies you can create.

- SelectCORS in theSecurity category.
- Provide a name, such as
Add CORSand then clickAdd.
About theTry now button
If this is your first time using the new version of the Proxy Editor, you will see the followingbanner at the top of theDevelop view:

Click theTry now button to display the newDevelop view.
Note: If you previouslyclicked theTry now button, it won't be displayed.TheDevelop view is shown below.



Handling CORS preflight requests
CORS preflight refers to sending a request to a server to verify if it supports CORS. Typical preflight responses include which origins the server will accept CORS requests from, a list of HTTP methods that are supported for CORS requests, headers that can be used as part of the resource request, the maximum time preflight response will be cached, and others. If the service does not indicate CORS support or does not wish to accept cross-origin requests from the client's origin, the cross-origin policy of the browser will be enforced and any cross-domain requests made from the client to interact with resources hosted on that server will fail.
Typically, CORS preflight requests are made with the HTTP OPTIONS method. When a server that supports CORS receives an OPTIONS request, it returns a set of CORS headers to the client that indicate its level of CORS support. As a result of this handshake, the client knows what it is allowed to request from the non-origin domain.
Note: If you have a Verify API key policy in the proxy endpoint PreFlow, it is applied to all the incoming requests. If you don't want to apply the policy for CORS preflight requests, add a condition to skip when the method is OPTIONS. For example, use the following API proxy configuration:<PreFlow name="PreFlow"> <Request> <Step> <Name>verify-api-key</Name> <Condition>request.verb != "OPTIONS"</Condition> </Step> </Request> <Response/></PreFlow>
For more information on preflight, refer to theCross-Origin Resource Sharing W3C Recommendation. There are in addition numerous blogs and articles on CORS that you can refer to.
Apigee does not include a CORS preflight solution out of the box, but it is possible to implement, as described in this section. The objective is for the proxy to evaluate an OPTIONS request in a conditional flow. The proxy can then send an appropriate response back to the client.
Let's look at a sample flow, and then discuss the parts that handle the preflight request:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><ProxyEndpoint name="default"> <Description/> <Flows><Flow name="OptionsPreFlight"> <Request> <Step> <Name>add-cors</Name> </Step> </Request> <Response/> <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition> </Flow> </Flows> <PreFlow name="PreFlow"> <Request/> <Response/> </PreFlow> <HTTPProxyConnection> <BasePath>/v1/cnc</BasePath> <VirtualHost>default</VirtualHost> <VirtualHost>secure</VirtualHost> </HTTPProxyConnection><RouteRule name="NoRoute"> <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition> </RouteRule> <RouteRule name="default"> <TargetEndpoint>default</TargetEndpoint> </RouteRule> <PostFlow name="PostFlow"> <Request/> <Response/> </PostFlow></ProxyEndpoint>
The key parts of this ProxyEndpoint are as follows:
- A RouteRule is created to a NULL target with a condition for the OPTIONS request. Note that there is no TargetEndpoint specified. If the OPTIONS request is received and the Origin and Access-Control-Request-Method request headers are not null, the proxy immediately returns the CORS headers in a response to the client (bypassing the actual default "backend" target). For details on flow conditions and RouteRule, seeConditions with flow variables.
<RouteRule name="NoRoute"> <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition></RouteRule>
- An OptionsPreFlight flow is created that adds an Add CORS policy, containing the CORS headers, to the flow if an OPTIONS request is received and the Origin and Access-Control-Request-Method request headers are not null.
<Flow name="OptionsPreFlight"> <Request> <Step> <Name>add-cors</Name> </Step> </Request> <Response/> <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition> </Flow>
Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2025-12-17 UTC.