Bulk Operation URL to download the data

Topic summary

Issue Identified:
A developer encountered problems downloading bulk operation data from Shopify. After receiving a completed webhook status and requesting the download URL, attempts to access it via browser or .NET HttpClient failed with a 400 Bad Request error.

Root Cause:
The URL returned by Shopify in the webhook response (data.node.url) was malformed, containing spaces and line breaks that prevented proper access.

Resolution:
User ‘agis’ solved the issue by cleaning the URL using JavaScript:

var cleanedUrl = url.replace(/\n|\r|\s/g,'');

Removing the whitespace and line break characters from the URL string allowed successful data download. The discussion appears resolved with this workaround.

Summarized with AI on November 19. AI used: claude-sonnet-4-5-20250929.

Hi,

I requested a bulk operation for which I received a Global ID then requested the URL to download the data. However, either trying this URL on the browser or using an HttpClient from .NET with Shopify API key and API Password, nothing seems to work.

After Shopify sent me a completed status in my webhook then I requested the URL and this is the response I had

{
    "data": {
        "node": {
            "url": "https:\/\/storage.googleapis.com\/shopify-tiers-assets-prod-us-east1\/9fzudf642tv8nyqltsx9utifk4yi?GoogleAccessId=assets-us-prod%40shopify-tiers.iam.gserviceaccount.com\u0026Expires=1678377402\u0026Signature=HPIARISmjX27T48UhLiyUQFCuG45X1DuCKXtyU04lQLw7NiFtfvVXCLjwmZh%2FA2KjqYcFlI3s7a9fM%2FIFhTmQORBGv7RTlAgUWzPzn2Ks4A50uyMM6LrXkLZ9JvaJdBZll%2FGNH0QePRn4BbiKEJ8wPZ9TGeif%2BkecLYn3p51iiW6LdYnWXoJk%2BrmeC31PgY0RQCkrxTV37%2FPpvDnpNDpqLcrYl4DttFzRRnJNqT5fS9%2FSTnrv1arT7TMNUJdQUyDfbklXwAsO9S05xA4RIaqV0VWfAJiqCrj5LUAjHUOr4m1CJ2M9prcu%2Bg8hTZ3hDdKpQLZMHkvYybzVD8cEHNnZg%3D%3D\u0026response-content-disposition=attachment%3B+filename%3D%22bulk-3226722795687.jsonl%22%3B+filename%2A%3DUTF-8%27%27bulk-3226722795687.jsonl\u0026response-content-type=application%2Fjsonl"
        }
    },
    "extensions": {
        "cost": {
            "requestedQueryCost": 1,
            "actualQueryCost": 1,
            "throttleStatus": {
                "maximumAvailable": 1000.0,
                "currentlyAvailable": 999,
                "restoreRate": 50.0
            }
        }
    }
}

Now either by web browser or by HttpClient I can’t get the data

Here’s the URL I’m using :

https://storage.googleapis.com/shopify-tiers-assets-prod-us-east1/ua46s9bdv03kwmlf8gefk2r8q9lg?GoogleAccessId=assets-us-prod@shopify-tiers.iam.gserviceaccount.com&Expires=1678383091&Signature=YFfnqn74LIRgOKo7oUGjSSNwdfXC059HztnaUpZH/9XvdlNBLWy+CmDnNMobX6aw3HjArQGB3EeW/Dzmdgk1SceNaWr2KIVQIa49nToTyxQSLWX0hJLT2YMUE/glDfieKyHChWBUyajIBxcqqDkCYOLY803yd38TrGWH/BpKkzm11VCt79NuOqNd9iQU9gAnrFFDMF6ZVbqn6v+BsSPuBOGeIZadmY6RUrl6cp3dG942hIkecnYFpazf3HJuLNr9l7G12uKpQlfew7oJgY26N7hrJZidhkaEb34WRIXmgJSeLwx/RITxrEbcpqpM/9+SyAjK93kA3RwMEMo8y6e9Ng==&response-content-disposition=attachment; filename="bulk-3227074035879.jsonl"; filename*=UTF-8''bulk-3227074035879.jsonl&response-content-type=application/jsonl

When using the browser :

<Error>
	<Code>MalformedSecurityHeader</Code>
	<Message>Your request has a malformed header.</Message>
	<ParameterName>signature</ParameterName>
	<Details>Signature was not base64 encoded</Details>
</Error>

When using HttpClient :

{
    "Version": {
        "Major": 1,
        "Minor": 1,
        "Build": -1,
        "Revision": -1,
        "MajorRevision": -1,
        "MinorRevision": -1
    },
    "Content": {
        "Headers": [{
                "Key": "Content-Type",
                "Value": ["application/xml; charset=UTF-8"]
            }, {
                "Key": "Content-Length",
                "Value": ["235"]
            }, {
                "Key": "Expires",
                "Value": ["Thu, 02 Mar 2023 17:33:47 GMT"]
            }
        ]
    },
    "StatusCode": 400,
    "ReasonPhrase": "Bad Request",
    "Headers": [{
            "Key": "X-GUploader-UploadID",
            "Value": ["ADPycduhx4OlLxKOqmJAWR7QG6Ma2StEOoB8Aaf_eBPu0qjZ4nBws0PQmeUB3TBjrSgKASFTt3Ig8ouuFjUSu0X9sl5Ylw"]
        }, {
            "Key": "Date",
            "Value": ["Thu, 02 Mar 2023 17:33:47 GMT"]
        }, {
            "Key": "Cache-Control",
            "Value": ["max-age=0, private"]
        }, {
            "Key": "Server",
            "Value": ["UploadServer"]
        }, {
            "Key": "Alt-Svc",
            "Value": ["h3=\u0022:443\u0022; ma=2592000", "h3-29=\u0022:443\u0022; ma=2592000", "h3-Q050=\u0022:443\u0022; ma=2592000", "h3-Q046=\u0022:443\u0022; ma=2592000", "h3-Q043=\u0022:443\u0022; ma=2592000", "quic=\u0022:443\u0022; ma=2592000"]
        }
    ],
    "TrailingHeaders": [],
    "RequestMessage": {
        "Version": {
            "Major": 1,
            "Minor": 1,
            "Build": -1,
            "Revision": -1,
            "MajorRevision": -1,
            "MinorRevision": -1
        },
        "VersionPolicy": 0,
        "Content": null,
        "Method": {
            "Method": "GET"
        },
        "RequestUri": "https://storage.googleapis.com/shopify-tiers-assets-prod-us-east1/ua46s9bdv03kwmlf8gefk2r8q9lg?GoogleAccessId=assets-us-prod@shopify-tiers.iam.gserviceaccount.com\u0026Expires=1678383091\u0026Signature=YFfnqn74LIRgOKo7oUGjSSNwdfXC059HztnaUpZH/9XvdlNBLWy\u002BCmDnNMobX6aw3HjArQGB3EeW/Dzmdgk1SceNaWr2KIVQIa49nToTyxQSLWX0hJLT2YMUE/glDfieKyHChWBUyajIBxcqqDkCYOLY803yd38TrGWH/BpKkzm11VCt79NuOqNd9iQU9gAnrFFDMF6ZVbqn6v\u002BBsSPuBOGeIZadmY6RUrl6cp3dG942hIkecnYFpazf3HJuLNr9l7G12uKpQlfew7oJgY26N7hrJZidhkaEb34WRIXmgJSeLwx/RITxrEbcpqpM/9\u002BSyAjK93kA3RwMEMo8y6e9Ng==\u0026response-content-disposition=attachment; filename=\u0022bulk-3227074035879.jsonl\u0022; filename*=UTF-8\u0027\u0027bulk-3227074035879.jsonl\u0026response-content-type=application/jsonl",
        "Headers": [{
                "Key": "Authorization",
                "Value": ["Basic YTBjYjcyMGJlMGMyYmM4ZDZiNThmYzk4ZjI3ZDEyNGQ6c2hwcGFfYzI3MDEyYjlkN2JkYjk4Yzc3YjJlZTZiZmI2OGNlNjk="]
            }, {
                "Key": "traceparent",
                "Value": ["00-d1aee17153c23c469e54f4d4e8d2af43-4790da114fb05e4f-00"]
            }
        ],
        "Properties": {},
        "Options": {}
    },
    "IsSuccessStatusCode": false
}

Hi,

I’m checking if anybody has an idea ?

I would appreciate a solution please.

It seems that the url returned by shopify in the webhook (data.node.url) is malformed because it has spaces and linebreaks in it.

Removing the linebreaks and spaces with

var cleanedUrl = url.replace(/\n|\r|\s/g, ‘’);

Solved the issue for me.